struct scanner_token *scan_filename(char *fname) { FILE *fp = fopen(fname, "r"); struct scanner_input *i = GC_malloc(sizeof(struct scanner_input)); struct scanner_token *tokens = NULL; if (fp == NULL) die("Could not open file \'%s\'\n", fname); i->fp = fp; i->filename = GC_strdup(fname); i->str = NULL; i->pos = 0; i->line_number = 1; tokens = scan(i, NULL); fclose(fp); return tokens; }
extern const char* Error_printMessagesStr(threadData_t *threadData,int warningsAsErrors) { std::string res = ErrorImpl__printMessagesStr(threadData,warningsAsErrors); return GC_strdup(res.c_str()); }
static struct scanner_token scan_next(struct scanner_input *I) { char c = 1; int i, num_invalid_chars = 0; struct scanner_token T; T.line = I->line_number; T.value = NULL; while (c != 0) { c = next_char(I); if (isalpha(c)) /* An identifier */ { char name[512]; /* Arbitrary limit to name length */ name[0] = c; i = 1; c = next_char(I); while (isalnum(c) || c == '_') { name[i++] = c; c = next_char(I); } name[i] = 0; put_back(I, c); if ( strcmp(name, "class") == 0 ) { T.type = TOK_CLASS; } else if ( strcmp(name, "end") == 0 ) { T.type = TOK_END; } else if ( strcmp(name, "return") == 0 ) { T.type = TOK_RETURN; } else { T.type = TOK_IDENTIFIER; T.value = GC_strdup(name); } return T; } /* FIXME: Need to check that there is only 1 '.' and 'e' in a number. * Also maybe make 'e' an actual operator instead because that would be cool */ if (isdigit(c)) { char num[512]; int ndots = 0; num[0] = c; i = 1; c = next_char(I); while (isdigit(c) || c == '.') { num[i++] = c; if (c == '.') ndots++; c = next_char(I); } num[i] = 0; put_back(I, c); if (ndots > 1) die("Invalid number: Too many decimal points", 1); T.type = (ndots == 0) ? TOK_INT : TOK_DECIMAL; /* It must be strdup'd to stop it being destroyed as soon as this loop returns */ T.value = GC_strdup(num); return T; } if (c == '=') { T.type = TOK_ASSIGN; /* Check it is =, not == */ c = next_char(I); if (c == '=') /* It must be comparison: == */ T.type = TOK_ISEQUAL; else put_back(I, c); return T; } if (c == '<') { T.type = TOK_LT; c = next_char(I); if (c == '=') T.type = TOK_LTE; else put_back(I, c); return T; } if (c == '>') { T.type = TOK_GT; c = next_char(I); if (c == '=') T.type = TOK_GTE; else put_back(I, c); return T; } if (c == '\"') { char *s = read_quoted_string(I); T.value = s; T.type = TOK_STRING; return T; } if (c == '#') { while (c != '\n') c = next_char(I); } if (isspace(c)) /* Ignore whitespace */ continue; switch (c) { case 0: T.type = TOK_EOF; return T; case '.': T.type = TOK_DOT; return T; case '+': T.type = TOK_ADD; return T; case '-': T.type = TOK_SUB; return T; case '*': T.type = TOK_MUL; return T; case '/': T.type = TOK_DIV; return T; case '(': T.type = TOK_OPEN_BRACKET; return T; case ')': T.type = TOK_CLOSED_BRACKET;return T; //case '{': T.type = TOK_STARTBLOCK; return T; //case '}': T.type = TOK_ENDBLOCK; return T; case ',': T.type = TOK_COMMA; return T; case ';': T.type = TOK_SEMICOLON; return T; default: if (num_invalid_chars++ < 1) fprintf(stderr, "Syntax error, line %lu: Invalid character \'%c\' (%d)\n", I->line_number, c, c); break; } } printf("EOF\n"); T.type = TOK_EOF; return T; }
extern const char* Error_printErrorsNoWarning(threadData_t *threadData) { std::string res = ErrorImpl__printErrorsNoWarning(threadData); return GC_strdup(res.c_str()); }