/* next error will still return 1 by default */ %{ #include "y.tab.h" #define FLEX_SCANNER #include "lint.h" #include "string.h" #include "config.h" #include "exec.h" #include "interpret.h" #include "instrs.h" int strict_types_flag; /* not used with this lexical analyzer... */ int current_line; int total_lines; /* Used to compute average compiled lines/s */ char *current_file; extern char *argument_name; int number(), lookupword(), string(), atoi(); /* * Flex doesn't handle negative characters, but this change will at least * not crash the game. */ #ifdef YY_FATAL_ERROR #undef YY_FATAL_ERROR #define YY_FATAL_ERROR(msg) \ { \ fputs( msg, stderr ); \ putc( '\n', stderr ); \ error(msg); \ } #endif #ifdef FLEX #define yywrap() 1 #endif /* * The number of arguments stated below, are used by the compiler. * If min == max, then no information has to be coded about the * actual number of arguments. Otherwise, the actual number of arguments * will be stored in the byte after the instruction. * A maximum value of -1 means unlimited maximum value. * * If an argument has type 0 (T_INVALID) specified, then no checks will * be done at run time. */ static struct keyword { char *word; short token; char min_args; /* Minimum number of arguments. */ char max_args; /* Maximum number of arguments. */ short ret_type; /* The return type used by the compiler. */ char arg_type1; /* Type of argument 1 */ char arg_type2; /* Type of argument 2 */ } predefs[] = { #include "efuns.i" }; /* I have no idea what these were supposed to do -- Raistlin {"add_adj" , F_ADD_ADJ }, {"add_subst" , F_ADD_SUBST }, */ #define NELEM(a) (sizeof (a) / sizeof (a)[0]) static struct keyword reswords[] = { { "break", F_BREAK, }, { "catch", F_CATCH, }, { "continue", F_CONTINUE, }, { "do", F_DO, }, { "else", F_ELSE, }, { "for", F_FOR, }, { "if", F_IF, }, { "inherit", F_INHERIT, }, { "int", F_INT, }, { "mixed", F_MIXED, }, { "nomask", F_NO_MASK, }, { "object", F_OBJECT, }, { "parse_command", F_PARSE_COMMAND, }, { "private", F_PRIVATE, }, { "protected", F_PROTECTED, }, { "public", F_PUBLIC, }, { "return", F_RETURN, }, { "sscanf", F_SSCANF, }, { "static", F_STATIC, }, { "status", F_STATUS, }, { "string", F_STRING_DECL, }, { "void", F_VOID, }, { "while", F_WHILE, }, }; extern char *local_names[]; extern int current_number_of_locals; extern char *string_copy(); void pre_processor_info(); %} #ifdef LEX %e 1500 %p 5000 %n 1000 %k 1000 %a 2500 %o 3000 #endif dec (0|[1-9][0-9]*) oct (0[0-7]+) hex (0[xX][0-9a-fA-F]+) ident ([_a-zA-Z][_a-zA-Z0-9]*) string (\"([^"\\\n]|\\\n|\\.)*\") %% ";" { return ';'; } "(" { return '('; } ")" { return ')'; } "," { return ','; } "{" { return '{'; } "}" { return '}'; } "++" { return F_INC; } "--" { return F_DEC; } "?" { return '?'; } ":" { return ':'; } "~" { return '~'; } "&&" { return F_LAND; } "&" { return '&'; } "&=" { return F_AND_EQ; } "||" { return F_LOR; } "|" { return '|'; } "|=" { return F_OR_EQ; } "^" { return '^'; } "^=" { return F_XOR_EQ; } "<<" { return F_LSH; } "<<=" { return F_LSH_EQ; } ">>" { return F_RSH; } ">>=" { return F_RSH_EQ; } "!" { return F_NOT; } "->" { return F_ARROW; } "=" { return '='; } "-" { return '-'; } "-=" { return F_SUB_EQ; } "+" { return '+'; } "+=" { return F_ADD_EQ; } "*" { return '*'; } "*=" { return F_MULT_EQ; } "%" { return '%'; } "%=" { return F_MOD_EQ; } "/" { return '/'; } "/=" { return F_DIV_EQ; } "<" { return '<'; } ">" { return '>'; } ">=" { return F_GE; } "<=" { return F_LE; } "==" { return F_EQ; } "!=" { return F_NE; } "::" { return F_COLON_COLON; } ^#.*$ { pre_processor_info(yytext); } "[" { return '['; } "]" { return ']'; } {dec} { return dec(yytext); } {hex} { return hex(yytext); } {oct} { return oct(yytext); } '.' { yylval.number = yytext[1]; return F_NUMBER; } {ident} { int i; if ((i = lookup_resword(yytext)) >= 0) return i; return ident(yytext); } {string} { return string(yytext); } [\t ] { break; } "\n" { current_line++; total_lines++; store_line_number_info(); } . { char buff[100]; sprintf(buff, "Illegal character '%c'", yytext[0]); yyerror(buff); } %% extern YYSTYPE yylval; #ifdef LEX int yywrap() { return 1; } #endif /* * debugging, gives the name of a single. */ int string(str) char *str; { char *p; p = (char *)string_copy(str); yylval.string = p; for (str++; str[1] != '\0'; str++, p++) { if (str[0] == '\\' && str[1] == '\n') str++, p--; /* ignore \n's at the end of a line -- R&R */ else if (str[0] == '\\' && str[1] == 'n') { *p = '\n'; str++; } else if (str[0] == '\\' && str[1] == 't') { *p = '\t'; str++; } else if (str[0] == '\\' && str[1] == '"') { /* LA */ *p = '"'; /* LA */ str++; /* LA */ if (!str[1]) { yyerror("Unterminated string"); break; } } else if (str[0] == '\\') { *p = str[1]; str++; } else *p = *str; } *p = '\0'; return F_STRING; } int dec(str) char *str; { int i; i = atoi(str); return number(i); } int hex(str) char *str; { int i; sscanf(str, "%x", &i); return number(i); } int oct(str) char *str; { int i; sscanf(str, "%x", &i); return number(i); } int number(i) int i; { if (i == 0) { yylval.number = 0; return F_CONST0; } if (i == 1) { yylval.number = 1; return F_CONST1; } yylval.number = i; return F_NUMBER; } void start_new_file(f) FILE *f; { extern int yyprevious; #ifdef FLEX yy_init = 1; #endif #ifdef LEX extern int yyprevious; /* KLUDGE! */ NLSTATE; yysptr = yysbuf; #endif yyin = f; } void pre_processor_info(str) char *str; { int line,i; char file[100]; if (sscanf(str, "# %d \"%s\"", &line, file) != 2) return; i = strlen(file); if (file[i-1] == '"') file[i-1] = '\0'; free(current_file); current_file = string_copy(file); current_line = line - 1; } #if 0 #ifdef LEX void fix_vars() { extern int yyprevious; current_line = 0; yyprevious = 10; yylineno = 1; yysptr = yysbuf; } #endif #endif struct instr instrs[256]; static void add_instr_name(name, n) char *name; int n; { instrs[n - F_OFFSET].name = name; } void init_num_args() { int i, n; for(i=0; i<NELEM(predefs); i++) { n = predefs[i].token - F_OFFSET; if (n < 0 || n > NELEM(instrs)) fatal("Token %s has illegal value %d.\n", predefs[i].word, n); instrs[n].min_arg = predefs[i].min_args; instrs[n].max_arg = predefs[i].max_args; instrs[n].name = predefs[i].word; instrs[n].type[0] = predefs[i].arg_type1; instrs[n].type[1] = predefs[i].arg_type2; instrs[n].ret_type = predefs[i].ret_type; } add_instr_name("<", F_LT); add_instr_name(">", F_GT); add_instr_name("<=", F_LE); add_instr_name(">=", F_GE); add_instr_name("==", F_EQ); add_instr_name("+=", F_ADD_EQ); add_instr_name("!", F_NOT); add_instr_name("index", F_INDEX_INSTR); add_instr_name("push_indexed_lvalue", F_PUSH_INDEXED_LVALUE); add_instr_name("identifier", F_IDENTIFIER); add_instr_name("local", F_LOCAL_NAME); add_instr_name("indirect", F_INDIRECT); add_instr_name("number", F_NUMBER); add_instr_name("push_local_variable_lvalue", F_PUSH_LOCAL_VARIABLE_LVALUE); add_instr_name("const1", F_CONST1); add_instr_name("subtract", F_SUBTRACT); add_instr_name("assign", F_ASSIGN); add_instr_name("pop", F_POP_VALUE); add_instr_name("const0", F_CONST0); add_instr_name("jump_when_zero", F_JUMP_WHEN_ZERO); add_instr_name("jump_when_non_zero", F_JUMP_WHEN_NON_ZERO); add_instr_name("||", F_LOR); add_instr_name("&&", F_LAND); add_instr_name("-=", F_SUB_EQ); add_instr_name("jump", F_JUMP); add_instr_name("return", F_RETURN); add_instr_name("sscanf", F_SSCANF); add_instr_name("string", F_STRING); add_instr_name("call", F_CALL_FUNCTION_BY_ADDRESS); add_instr_name("aggregate", F_AGGREGATE); add_instr_name("push_identifier_lvalue", F_PUSH_IDENTIFIER_LVALUE); add_instr_name("+", F_ADD); add_instr_name("!=", F_NE); add_instr_name("dup", F_DUP); add_instr_name("catch", F_CATCH); add_instr_name("neg", F_NEGATE); } char *get_f_name(n) int n; { if (instrs[n-F_OFFSET].name) return instrs[n-F_OFFSET].name; return "<OTHER>"; } static int lookupword(s, words, h) char *s; struct keyword *words; int h; { int i, l, r; l = 0; for(;;) { i = (l+h)/2; r = strcmp(s, words[i].word); if (r == 0) return words[i].token; else if (l == i) return -1; else if (r < 0) h = i; else l = i; } } static int lookup_resword(s) char *s; { return lookupword(s, reswords, NELEM(reswords)); } int lookup_predef(s) char *s; { return lookupword(s, predefs, NELEM(predefs)); } static int islocal(str) char *str; { int i; for (i=current_number_of_locals-1; i>=0; i--) { if (strcmp(local_names[i], str) == 0) return i; } return -1; } static int ident(str) char *str; { int i; i = islocal(str); if (i >= 0) { yylval.number = i; return F_LOCAL_NAME; } yylval.string = string_copy(str); return F_IDENTIFIER; }