%include{ #include "xlat.h" #include "xlat-parse.h" #include #include int yyerror (char *s); typedef struct _Symbol { struct _Symbol *Next; int Value; char Sym[1]; } Symbol; static bool FindToken (char *tok, int *type); static void AddSym (char *sym, int val); static bool FindSym (char *sym, Symbol **val); static int EnumVal; struct ListFilter { WORD filter; BYTE value; }; typedef struct _morefilters { struct _morefilters *next; struct ListFilter filter; } MoreFilters; typedef struct _morelines { struct _morelines *next; BoomArg arg; } MoreLines; typedef struct _specialargs { BYTE addflags; BYTE args[5]; } SpecialArgs; typedef struct _boomarg { BYTE constant; WORD mask; MoreFilters *filters; } ParseBoomArg; typedef union YYSTYPE { int val; char sym[80]; char string[80]; Symbol *symval; } YYSTYPE; #include #include int yylex (YYSTYPE *yylval) { char token[80]; int toksize; int c; loop: while (Source == NULL) { if (!EndFile ()) return 0; } while (isspace (c = fgetc (Source)) && c != EOF) { if (c == '\n') SourceLine++; } if (c == EOF) { if (EndFile ()) goto loop; return 0; } if (isdigit (c)) { int buildup = c - '0'; if (c == '0') { c = fgetc (Source); if (c == 'x' || c == 'X') { for (;;) { c = fgetc (Source); if (isdigit (c)) { buildup = (buildup<<4) + c - '0'; } else if (c >= 'a' && c <= 'f') { buildup = (buildup<<4) + c - 'a' + 10; } else if (c >= 'A' && c <= 'F') { buildup = (buildup<<4) + c - 'A' + 10; } else { ungetc (c, Source); yylval->val = buildup; return NUM; } } } else { ungetc (c, Source); } } while (isdigit (c = fgetc (Source))) { buildup = buildup*10 + c - '0'; } ungetc (c, Source); yylval->val = buildup; return NUM; } if (isalpha (c)) { int buildup = 0; token[0] = c; toksize = 1; while (toksize < 79 && (isalnum (c = fgetc (Source)) || c == '_')) { token[toksize++] = c; } token[toksize] = 0; if (toksize == 79 && isalnum (c)) { while (isalnum (c = fgetc (Source))) ; } ungetc (c, Source); if (FindToken (token, &buildup)) { return buildup; } if (FindSym (token, &yylval->symval)) { return SYMNUM; } strcpy (yylval->sym, token); return SYM; } if (c == '/') { c = fgetc (Source); if (c == '*') { for (;;) { while ((c = fgetc (Source)) != '*' && c != EOF) { if (c == '\n') SourceLine++; } if (c == EOF) return 0; if ((c = fgetc (Source)) == '/') goto loop; if (c == EOF) return 0; ungetc (c, Source); } } else if (c == '/') { while ((c = fgetc (Source)) != '\n' && c != EOF) ; if (c == '\n') SourceLine++; else if (c == EOF) return 0; goto loop; } else { ungetc (c, Source); return DIVIDE; } } if (c == '"') { int tokensize = 0; while ((c = fgetc (Source)) != '"' && c != EOF) { yylval->string[tokensize++] = c; } yylval->string[tokensize] = 0; return STRING; } if (c == '|') { c = fgetc (Source); if (c == '=') return OR_EQUAL; ungetc (c, Source); return OR; } switch (c) { case '^': return XOR; case '&': return AND; case '-': return MINUS; case '+': return PLUS; case '*': return MULTIPLY; case '(': return LPAREN; case ')': return RPAREN; case ',': return COMMA; case '{': return LBRACE; case '}': return RBRACE; case '=': return EQUALS; case ';': return SEMICOLON; case ':': return COLON; case '[': return LBRACKET; case ']': return RBRACKET; default: return 0; } } void *ParseAlloc(void *(*mallocProc)(size_t)); void Parse(void *yyp, int yymajor, YYSTYPE yyminor); void ParseFree(void *p, void (*freeProc)(void*)); void ParseTrace(FILE *TraceFILE, char *zTracePrompt); void yyparse (void) { void *pParser = ParseAlloc (malloc); YYSTYPE token; int tokentype; while ((tokentype = yylex(&token)) != 0) { Parse (pParser, tokentype, token); } memset (&token, 0, sizeof(token)); Parse (pParser, 0, token); ParseFree (pParser, free); } static Symbol *FirstSym; static void AddSym (char *sym, int val) { Symbol *syme = malloc (strlen (sym) + sizeof(Symbol)); syme->Next = FirstSym; syme->Value = val; strcpy (syme->Sym, sym); FirstSym = syme; } static bool FindSym (char *sym, Symbol **val) { Symbol *syme = FirstSym; while (syme != NULL) { if (strcmp (syme->Sym, sym) == 0) { *val = syme; return 1; } syme = syme->Next; } return 0; } static bool FindToken (char *tok, int *type) { static const char tokens[][8] = { "endl", "print", "include", "special", "define", "enum", "arg5", "arg4", "arg3", "arg2", "flags", "lineid", "tag" }; static const short types[] = { ENDL, PRINT, INCLUDE, SPECIAL, DEFINE, ENUM, ARG5, ARG4, ARG3, ARG2, FLAGS, LINEID, TAG }; int i; for (i = sizeof(tokens)/sizeof(tokens[0])-1; i >= 0; i--) { if (strcmp (tok, tokens[i]) == 0) { *type = types[i]; return 1; } } return 0; } int yyerror (char *s) { if (SourceName != NULL) printf ("%s, line %d: %s\n", SourceName, SourceLine, s); else printf ("%s\n", s); return 0; } } %token_type {YYSTYPE} %syntax_error {yyerror("syntax error");} %type exp {int} %type special_args {SpecialArgs} %type list_val {struct ListFilter} %type arg_list {MoreFilters *} %type boom_args {ParseBoomArg} %type boom_op {int} %type boom_selector {int} %type boom_line {BoomArg} %type boom_body {MoreLines *} %type maybe_argcount {int} %left OR. %left XOR. %left AND. %left MINUS PLUS. %left MULTIPLY DIVIDE. %left NEG. main ::= translation_unit. exp(A) ::= NUM(B). { A = B.val; } exp(A) ::= SYMNUM(B). { A = B.symval->Value; } exp(A) ::= exp(B) PLUS exp(C). { A = B + C; } exp(A) ::= exp(B) MINUS exp(C). { A = B - C; } exp(A) ::= exp(B) MULTIPLY exp(C). { A = B * C; } exp(A) ::= exp(B) DIVIDE exp(C). { A = B / C; } exp(A) ::= exp(B) OR exp(C). { A = B | C; } exp(A) ::= exp(B) AND exp(C). { A = B & C; } exp(A) ::= exp(B) XOR exp(C). { A = B ^ C; } exp(A) ::= MINUS exp(B). [NEG] { A = -B; } exp(A) ::= LPAREN exp(B) RPAREN. { A = B; } translation_unit ::= . /* empty */ translation_unit ::= external_declaration. external_declaration ::= define_statement. external_declaration ::= include_statement. external_declaration ::= print_statement. external_declaration ::= enum_statement. external_declaration ::= linetype_declaration. external_declaration ::= boom_declaration. external_declaration ::= special_declaration. print_statement ::= PRINT LPAREN print_list RPAREN. { printf ("\n"); } print_list ::= . /* EMPTY */ print_list ::= print_item. print_list ::= print_item COMMA print_list. print_item ::= STRING(A). { printf ("%s", A.string); } print_item ::= exp(A). { printf ("%d", A); } print_item ::= ENDL. { printf ("\n"); } define_statement ::= DEFINE SYM(A) LPAREN exp(B) RPAREN. { AddSym (A.sym, B); } include_statement ::= INCLUDE STRING(A). { IncludeFile (A.string); } enum_statement ::= enum_open enum_list RBRACE. enum_open ::= ENUM LBRACE. { EnumVal = 0; } enum_list ::= . /* empty */ enum_list ::= single_enum. enum_list ::= single_enum COMMA enum_list. single_enum ::= SYM(A). { AddSym (A.sym, EnumVal++); } single_enum ::= SYM(A) EQUALS exp(B). { AddSym (A.sym, EnumVal = B); } /* special declarations work just like they do for ACS, so * specials can be defined just by including zspecial.acs */ special_declaration ::= SPECIAL special_list SEMICOLON. special_list ::= special_def. special_list ::= special_list COMMA special_def. special_def ::= exp(A) COLON SYM(B) LPAREN maybe_argcount RPAREN. { AddSym (B.sym, A); } special_def ::= exp COLON SYMNUM(B) LPAREN maybe_argcount RPAREN. { printf ("%s, line %d: %s is already defined\n", SourceName, SourceLine, B.symval->Sym); } maybe_argcount ::= . /* empty */ maybe_argcount ::= exp. maybe_argcount ::= exp COMMA exp. linetype_declaration ::= exp(linetype) EQUALS exp(flags) COMMA exp(special) LPAREN special_args(arg) RPAREN. { Simple[linetype].NewSpecial = special; Simple[linetype].Flags = flags | arg.addflags; Simple[linetype].Args[0] = arg.args[0]; Simple[linetype].Args[1] = arg.args[1]; Simple[linetype].Args[2] = arg.args[2]; Simple[linetype].Args[3] = arg.args[3]; Simple[linetype].Args[4] = arg.args[4]; } linetype_declaration ::= exp EQUALS exp COMMA SYM(S) LPAREN special_args RPAREN. { printf ("%s, line %d: %s is undefined\n", SourceName, SourceLine, S.sym); } boom_declaration ::= LBRACKET exp(special) RBRACKET LPAREN exp(firsttype) COMMA exp(lasttype) RPAREN LBRACE boom_body(stores) RBRACE. { if (NumBoomish == MAX_BOOMISH) { MoreLines *probe = stores; while (probe != NULL) { MoreLines *next = probe->next; free (probe); probe = next; } printf ("%s, line %d: Too many BOOM translators\n", SourceName, SourceLine); } else { int i; MoreLines *probe; Boomish[NumBoomish].FirstLinetype = firsttype; Boomish[NumBoomish].LastLinetype = lasttype; Boomish[NumBoomish].NewSpecial = special; for (i = 0, probe = stores; probe != NULL; i++) { MoreLines *next = probe->next;; if (i < MAX_BOOMISH_EXEC) { Boomish[NumBoomish].Args[i] = probe->arg; } else if (i == MAX_BOOMISH_EXEC) { printf ("%s, line %d: Too many commands for this BOOM translator\n", SourceName, SourceLine); } free (probe); probe = next; } if (i < MAX_BOOMISH_EXEC) { Boomish[NumBoomish].Args[i].bDefined = 0; } NumBoomish++; } } boom_body(A) ::= . /* empty */ { A = NULL; } boom_body(A) ::= boom_line(B) boom_body(C). { A = malloc (sizeof(MoreLines)); A->next = C; A->arg = B; } boom_line(A) ::= boom_selector(sel) boom_op(op) boom_args(args). { A.bDefined = 1; A.bOrExisting = (op == OR_EQUAL); A.bUseConstant = (args.filters == NULL); A.ArgNum = sel; A.ConstantValue = args.constant; A.AndValue = args.mask; if (args.filters != NULL) { int i; MoreFilters *probe; for (i = 0, probe = args.filters; probe != NULL; i++) { MoreFilters *next = probe->next; if (i < 15) { A.ResultFilter[i] = probe->filter.filter; A.ResultValue[i] = probe->filter.value; } else if (i == 15) { yyerror ("Lists can only have 15 elements"); } free (probe); probe = next; } A.ListSize = i > 15 ? 15 : i; } } boom_selector(A) ::= FLAGS. { A = 4; } boom_selector(A) ::= ARG2. { A = 0; } boom_selector(A) ::= ARG3. { A = 1; } boom_selector(A) ::= ARG4. { A = 2; } boom_selector(A) ::= ARG5. { A = 3; } boom_op(A) ::= EQUALS. { A = '='; } boom_op(A) ::= OR_EQUAL. { A = OR_EQUAL; } boom_args(A) ::= exp(B). { A.constant = B; A.filters = NULL; } boom_args(A) ::= exp(B) LBRACKET arg_list(C) RBRACKET. { A.mask = B; A.filters = C; } arg_list(A) ::= list_val(B). { A = malloc (sizeof(MoreFilters)); A->next = NULL; A->filter = B; } arg_list(A) ::= list_val(B) COMMA arg_list(C). { A = malloc (sizeof(MoreFilters)); A->next = C; A->filter = B; } list_val(A) ::= exp(B) COLON exp(C). { A.filter = B; A.value = C; } special_args(Z) ::= . /* empty */ { Z.addflags = 0; memset (Z.args, 0, 5); } special_args(Z) ::= TAG. { Z.addflags = SIMPLE_HASTAGAT1; memset (Z.args, 0, 5); } special_args(Z) ::= TAG COMMA exp(B). { Z.addflags = SIMPLE_HASTAGAT1; Z.args[0] = 0; Z.args[1] = B; Z.args[2] = 0; Z.args[3] = 0; Z.args[4] = 0; } special_args(Z) ::= TAG COMMA exp(B) COMMA exp(C). { Z.addflags = SIMPLE_HASTAGAT1; Z.args[0] = 0; Z.args[1] = B; Z.args[2] = C; Z.args[3] = 0; Z.args[4] = 0; } special_args(Z) ::= TAG COMMA exp(B) COMMA exp(C) COMMA exp(D). { Z.addflags = SIMPLE_HASTAGAT1; Z.args[0] = 0; Z.args[1] = B; Z.args[2] = C; Z.args[3] = D; Z.args[4] = 0; } special_args(Z) ::= TAG COMMA exp(B) COMMA exp(C) COMMA exp(D) COMMA exp(E). { Z.addflags = SIMPLE_HASTAGAT1; Z.args[0] = 0; Z.args[1] = B; Z.args[2] = C; Z.args[3] = D; Z.args[4] = E; } special_args(Z) ::= TAG COMMA TAG. { Z.addflags = SIMPLE_HAS2TAGS; Z.args[0] = Z.args[1] = 0; Z.args[2] = 0; Z.args[3] = 0; Z.args[4] = 0; } special_args(Z) ::= TAG COMMA TAG COMMA exp(C). { Z.addflags = SIMPLE_HAS2TAGS; Z.args[0] = Z.args[1] = 0; Z.args[2] = C; Z.args[3] = 0; Z.args[4] = 0; } special_args(Z) ::= TAG COMMA TAG COMMA exp(C) COMMA exp(D). { Z.addflags = SIMPLE_HAS2TAGS; Z.args[0] = Z.args[1] = 0; Z.args[2] = C; Z.args[3] = D; Z.args[4] = 0; } special_args(Z) ::= TAG COMMA TAG COMMA exp(C) COMMA exp(D) COMMA exp(E). { Z.addflags = SIMPLE_HAS2TAGS; Z.args[0] = Z.args[1] = 0; Z.args[2] = C; Z.args[3] = D; Z.args[4] = E; } special_args(Z) ::= LINEID. { Z.addflags = SIMPLE_HASLINEID; memset (Z.args, 0, 5); } special_args(Z) ::= LINEID COMMA exp(B). { Z.addflags = SIMPLE_HASLINEID; Z.args[0] = 0; Z.args[1] = B; Z.args[2] = 0; Z.args[3] = 0; Z.args[4] = 0; } special_args(Z) ::= LINEID COMMA exp(B) COMMA exp(C). { Z.addflags = SIMPLE_HASLINEID; Z.args[0] = 0; Z.args[1] = B; Z.args[2] = C; Z.args[3] = 0; Z.args[4] = 0; } special_args(Z) ::= LINEID COMMA exp(B) COMMA exp(C) COMMA exp(D). { Z.addflags = SIMPLE_HASLINEID; Z.args[0] = 0; Z.args[1] = B; Z.args[2] = C; Z.args[3] = D; Z.args[4] = 0; } special_args(Z) ::= LINEID COMMA exp(B) COMMA exp(C) COMMA exp(D) COMMA exp(E). { Z.addflags = SIMPLE_HASLINEID; Z.args[0] = 0; Z.args[1] = B; Z.args[2] = C; Z.args[3] = D; Z.args[4] = E; } special_args(Z) ::= exp(A). { Z.addflags = 0; Z.args[0] = A; Z.args[1] = 0; Z.args[2] = 0; Z.args[3] = 0; Z.args[4] = 0; } special_args(Z) ::= exp(A) COMMA exp(B). { Z.addflags = 0; Z.args[0] = A; Z.args[1] = B; Z.args[2] = 0; Z.args[3] = 0; Z.args[4] = 0; } special_args(Z) ::= exp(A) COMMA exp(B) COMMA exp(C). { Z.addflags = 0; Z.args[0] = A; Z.args[1] = B; Z.args[2] = C; Z.args[3] = 0; Z.args[4] = 0; } special_args(Z) ::= exp(A) COMMA exp(B) COMMA exp(C) COMMA exp(D). { Z.addflags = 0; Z.args[0] = A; Z.args[1] = B; Z.args[2] = C; Z.args[3] = D; Z.args[4] = 0; } special_args(Z) ::= exp(A) COMMA exp(B) COMMA exp(C) COMMA exp(D) COMMA exp(E). { Z.addflags = 0; Z.args[0] = A; Z.args[1] = B; Z.args[2] = C; Z.args[3] = D; Z.args[4] = E; } special_args(Z) ::= exp(A) COMMA TAG. { Z.addflags = SIMPLE_HASTAGAT2; Z.args[0] = A; Z.args[1] = 0; Z.args[2] = 0; Z.args[3] = 0; Z.args[4] = 0; } special_args(Z) ::= exp(A) COMMA TAG COMMA exp(C). { Z.addflags = SIMPLE_HASTAGAT2; Z.args[0] = A; Z.args[1] = 0; Z.args[2] = C; Z.args[3] = 0; Z.args[4] = 0; } special_args(Z) ::= exp(A) COMMA TAG COMMA exp(C) COMMA exp(D). { Z.addflags = SIMPLE_HASTAGAT2; Z.args[0] = A; Z.args[1] = 0; Z.args[2] = C; Z.args[3] = D; Z.args[4] = 0; } special_args(Z) ::= exp(A) COMMA TAG COMMA exp(C) COMMA exp(D) COMMA exp(E). { Z.addflags = SIMPLE_HASTAGAT2; Z.args[0] = A; Z.args[1] = 0; Z.args[2] = C; Z.args[3] = D; Z.args[4] = E; } special_args(Z) ::= exp(A) COMMA exp(B) COMMA TAG. { Z.addflags = SIMPLE_HASTAGAT3; Z.args[0] = A; Z.args[1] = B; Z.args[2] = 0; Z.args[3] = 0; Z.args[4] = 0; } special_args(Z) ::= exp(A) COMMA exp(B) COMMA TAG COMMA exp(D). { Z.addflags = SIMPLE_HASTAGAT3; Z.args[0] = A; Z.args[1] = B; Z.args[2] = 0; Z.args[3] = D; Z.args[4] = 0; } special_args(Z) ::= exp(A) COMMA exp(B) COMMA TAG COMMA exp(D) COMMA exp(E). { Z.addflags = SIMPLE_HASTAGAT3; Z.args[0] = A; Z.args[1] = B; Z.args[2] = 0; Z.args[3] = D; Z.args[4] = E; } special_args(Z) ::= exp(A) COMMA exp(B) COMMA exp(C) COMMA TAG. { Z.addflags = SIMPLE_HASTAGAT4; Z.args[0] = A; Z.args[1] = B; Z.args[2] = C; Z.args[3] = 0; Z.args[4] = 0; } special_args(Z) ::= exp(A) COMMA exp(B) COMMA exp(C) COMMA TAG COMMA exp(E). { Z.addflags = SIMPLE_HASTAGAT4; Z.args[0] = A; Z.args[1] = B; Z.args[2] = C; Z.args[3] = 0; Z.args[4] = E; } special_args(Z) ::= exp(A) COMMA exp(B) COMMA exp(C) COMMA exp(D) COMMA TAG. { Z.addflags = SIMPLE_HASTAGAT5; Z.args[0] = A; Z.args[1] = B; Z.args[2] = C; Z.args[3] = D; Z.args[4] = 0; }