%{ /* qp-lex.l lexer for QuakePascal Copyright (C) 2011 Bill Currie Author: Bill Currie Date: 2011/01/06 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to: Free Software Foundation, Inc. 59 Temple Place - Suite 330 Boston, MA 02111-1307, USA */ #ifdef HAVE_CONFIG_H # include "config.h" #endif static __attribute__ ((used)) const char rcsid[] = "$Id$"; #include "QF/hash.h" #include "debug.h" #include "diagnostic.h" #include "expr.h" #include "grab.h" #include "qfcc.h" #include "strpool.h" #include "symtab.h" #include "type.h" #include "qp-parse.h" #ifndef YY_PROTO # define YY_PROTO(x) x #else # define YY_FLEX_REALLOC_HACK #endif int yyget_lineno (void); FILE *yyget_in (void); FILE *yyget_out (void); int yyget_leng (void); char *yyget_text (void); void yyset_lineno (int line_number); void yyset_in (FILE * in_str); void yyset_out (FILE * out_str); int yyget_debug (void); void yyset_debug (int bdebug); int yylex_destroy (void); #define YY_NO_UNPUT #define YY_DECL int yylex YY_PROTO(( void )) YY_DECL; static int keyword_or_id (const char *token); static int convert_relop (const char *relop); %} s [ \t] m [\-+] D [0-9] X [0-9a-fA-F] ID [a-zA-Z_][0-9a-zA-Z_]* FLOAT ({D}+|{D}*\.{D}+|{D}+\.{D}*)([eE]{m}?{D}+)? INTEGER ({D}+|0[xX]{X}+) RELOP (=|<>|[<>]=?) ADDOP [\-+] MULOP [*/] ASSIGNOP := RANGE \.\. ELLIPSIS \.\.\. FRAMEID {ID}(\.{ID})* %x GRAB_FRAME GRAB_OTHER COMMENT %% grab_frame = GRAB_FRAME; grab_other = GRAB_OTHER; "{" { BEGIN (COMMENT); } "{" { warning (0, "nested { in comment"); } "}" { BEGIN (INITIAL); } "(*" { BEGIN (COMMENT); } "(*" { warning (0, "nested (* in comment"); } "*)" { BEGIN (INITIAL); } \r*\n { pr.source_line++; } . /* nothing to do, with people like you */ <> { error (0, "EOF in comment"); return 0; } "//".* /* nothing to do, with people like you */ ^#{s}+{D}+{s}+\"(\.|[^"\n])*\".*$ { line_info (yytext + 1); } ^#line{s}+{D}+{s}+\"(\.|[^"\n])*\".*$ { line_info (yytext + 1); } {INTEGER} { int i = strtol (yytext, 0, 0); yylval.expr = new_integer_expr (i); return CONST; } {FLOAT} { float f = strtof (yytext, 0); yylval.expr = new_float_expr (f); return CONST; } {ID} return keyword_or_id (yytext); \"(\\.|[^"\\])*\" { const char *s = make_string (yytext, 0); yylval.expr = new_string_expr (s); return CONST; } '{s}*{m}{FLOAT}{s}+{m}{FLOAT}{s}+{m}{FLOAT}{s}*' { vec3_t v; sscanf (yytext, "' %f %f %f '", &v[0], &v[1], &v[2]); yylval.expr = new_vector_expr (v); return CONST; } '{s}*{m}{FLOAT}{s}+{m}{FLOAT}{s}+{m}{FLOAT}{s}+{m}{FLOAT}{s}*' { quat_t q; sscanf (yytext, "' %f %f %f %f'", &q[0], &q[1], &q[2], &q[3]); yylval.expr = new_quaternion_expr (q); return CONST; } {RELOP} { yylval.op = convert_relop (yytext); return RELOP; } {ADDOP} { yylval.op = yytext[0]; return ADDOP; } {MULOP} { yylval.op = yytext[0]; return MULOP; } {ASSIGNOP} return ASSIGNOP; {RANGE} return RANGE; {ELLIPSIS} return ELLIPSIS; [!(){}.&|^~\[\];,#%?:] return yytext[0]; "$"{s}*{FRAMEID} { int ret = do_grab (yytext); if (ret >= 0) { yylval.expr = new_integer_expr (ret); return CONST; } else { BEGIN (-ret); } } {FRAMEID} add_frame_macro (yytext); [^\r\n]* /* skip */ <*>\r*\n { pr.source_line++; BEGIN (INITIAL); } <*>{s}* /* skip whitespace */ <*>. error (0, "all your typo are belong to us"); %% int yywrap (void) { return 1; } typedef struct { const char *name; int value; type_t *type; } keyword_t; static keyword_t keywords[] = { {"real", TYPE, &type_float}, {"string", TYPE, &type_string}, {"vector", TYPE, &type_vector}, {"entity", TYPE, &type_entity}, {"quaternion", TYPE, &type_quaternion}, {"integer", TYPE, &type_integer}, {"program", PROGRAM, 0}, {"var", VAR, 0}, {"array", ARRAY, 0}, {"of", OF, 0}, {"function", FUNCTION, 0}, {"procedure", PROCEDURE, 0}, {"begin", PBEGIN, 0}, {"end", END, 0}, {"if", IF, 0}, {"then", THEN, 0}, {"else", ELSE, 0}, {"while", WHILE, 0}, {"do", DO, 0}, {"or", ADDOP, 0}, {"div", MULOP, 0}, {"mod", MULOP, 0}, {"and", MULOP, 0}, {"not", NOT, 0}, {"return", RETURN, 0}, }; static const char * keyword_get_key (void *kw, void *unused) { return ((keyword_t *) kw)->name; } static int keyword_or_id (const char *token) { static hashtab_t *keyword_tab; keyword_t *keyword; symbol_t *sym; if (!keyword_tab) { size_t i; keyword_tab = Hash_NewTable (1021, keyword_get_key, 0, 0); for (i = 0; i < sizeof (keywords) / sizeof (keywords[0]); i++) Hash_Add (keyword_tab, &keywords[i]); } keyword = Hash_Find (keyword_tab, token); if (keyword) { if (keyword->value == ADDOP || keyword->value == MULOP) { yylval.op = token[0]; } else { yylval.type = keyword->type; } return keyword->value; } sym = symtab_lookup (current_symtab, token); if (!sym) sym = new_symbol (token); if (sym->sy_type == sy_type) { yylval.type = sym->type; return TYPE_NAME; } yylval.symbol = sym; return ID; } static int convert_relop (const char *relop) { switch (relop[0]) { case '=': return EQ; case '<': switch (relop[1]) { case 0: return LT; case '>': return NE; case '=': return LE; } break; case '>': switch (relop[1]) { case 0: return GT; case '=': return GE; } break; } error (0, "internal: bad relop %s", relop); return EQ; } #ifdef YY_FLEX_REALLOC_HACK static __attribute__ ((used)) void *(*const yy_flex_realloc_hack)(void *,yy_size_t) = yy_flex_realloc; #else static __attribute__ ((used)) void (*yyunput_hack)(int, char*) = yyunput; static __attribute__ ((used)) int (*input_hack)(void) = input; #endif