#include "growable.h"
#include "parser.h"
-static inline int read_number(struct ast_item *ai) {
+static inline int read_number(FILE *fh, struct ast_item *ai) {
int c;
intmax_t new_value;
- while (isdigit(c = getc(stdin))) {
+ while (isdigit(c = getc(fh))) {
new_value = ai->u.i * 10 + c - '0';
if (new_value / 10 != ai->u.i) {
fprintf(stderr, "Error: Overflow.\n");
ai->u.i = new_value;
}
if (c != EOF)
- ungetc(c, stdin);
+ ungetc(c, fh);
return 0;
}
-static inline int read_ident_or_keyword(int c, struct ast_item *ai) {
- struct growable s = EMPTY_GROWABLE(1);
+static inline int read_ident_or_keyword(
+ FILE *fh, struct growable *buffer, int c, struct ast_item *ai
+) {
+ buffer->len = 0;
do {
- if (growable_grow(&s, s.len + 1) < 0)
+ if (growable_grow(buffer, buffer->len + 1) < 0)
return -1;
- ((char*)s.data)[s.len++] = c;
- c = getc(stdin);
+ ((char*)buffer->data)[buffer->len++] = c;
+ c = getc(fh);
} while (isalnum(c) || c == '_');
if (c != EOF)
- ungetc(c, stdin);
- if (growable_grow(&s, s.len + 1) < 0)
+ ungetc(c, fh);
+ if (growable_grow(buffer, buffer->len + 1) < 0)
return -1;
- ((char*)s.data)[s.len++] = '\0';
- if (strcasecmp(s.data, "goto") == 0) {
+ if (buffer->len == 4 && strncasecmp(buffer->data, "goto", 4) == 0) {
ai->type = AST_ITEM_GOTO;
- growable_cleanup(s);
return 0;
}
ai->type = AST_ITEM_IDENT;
- ai->u.s = s.data;
+ ai->u.s = strndup(buffer->data, buffer->len);
+ if (ai->u.s == NULL) {
+ perror("strndup");
+ return -1;
+ }
return 0;
}
-int parse_input(struct program *p) {
+int parse_input(FILE *fh, struct program *p) {
int c;
struct ast_item ai;
- while ((c = getc(stdin)) != EOF) {
+ while ((c = getc(fh)) != EOF) {
memset(&ai.u, 0, sizeof ai.u);
switch (c) {
case '+':
if (isdigit(c)) {
ai.type = AST_ITEM_INT;
ai.u.i = c - '0';
- if (read_number(&ai) < 0)
+ if (read_number(fh, &ai) < 0)
return -1;
goto add_item;
} else if (isalpha(c) || c == '_') {
- if (read_ident_or_keyword(c, &ai) < 0)
+ if (read_ident_or_keyword(fh, &p->buffer, c, &ai) < 0)
return -1;
goto add_item;
} else if (isspace(c))
return -1;
memcpy(&GET_ITEM(*p, p->ast_items.len++), &ai, sizeof ai);
}
- if (ferror(stdin)) {
+ if (ferror(fh)) {
fprintf(stderr, "Error: read error.\n");
return -1;
}