X-Git-Url: http://git.draconx.ca/gitweb/gob-dx.git/blobdiff_plain/40647d7b7b7fbeae828e0a032a3c3a5f204cdfa8..96e3b08533ea7fc6bd4b4de58849da0dec72411c:/src/lexer.l diff --git a/src/lexer.l b/src/lexer.l index 320e25b..b25574b 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -23,16 +23,23 @@ #include "config.h" #include #include +#include +#include "treefuncs.h" #include "parse.h" #include "main.h" - -extern gboolean for_cpp; +#include "util.h" static int parenth_depth = 0; static int before_comment = INITIAL; -static int class_after_c = FALSE; -static int header_c = FALSE; +static gboolean class_after_c = FALSE; +static int code_type = CCODE; +static int before_string; +static int property_paren_depth = 0; + +/* GTK+ doc stuff */ +static char *gtk_doc_func = NULL; /* current gtk-doc func */ +GHashTable *gtk_doc_hash = NULL; static GString *cbuf = NULL; int ccode_line = 1; @@ -42,14 +49,16 @@ GList *include_files = NULL; static int look_for_includes = 0; int line_no = 1; +/* last filename parsed from a #line directive */ +char *hline_filename = NULL; static void clear_cbuf(void) { if(!cbuf) { - cbuf = g_string_new(""); + cbuf = g_string_new(NULL); } else { - cbuf = g_string_assign(cbuf,""); + cbuf = g_string_assign(cbuf, ""); } } @@ -63,21 +72,113 @@ add_to_cbuf(char *s) } } +static void +add_gtk_doc_func(void) +{ + if(!gtk_doc_func) + return; + + if(!gtk_doc_hash) + gtk_doc_hash = g_hash_table_new(g_str_hash, g_str_equal); + g_hash_table_insert(gtk_doc_hash, gtk_doc_func, g_strdup(cbuf->str)); + clear_cbuf(); + + gtk_doc_func = NULL; +} + +/* Ugly warning avoiding */ +#ifdef FLEX_SCANNER +int yylex(void); +#endif + %} %x COMMENT %x C_CODE -%x C_CODE_STRING +%x CODE_STRING %x CLASS_CODE %x CLASS_CODE_I +%x PROPERTY_CODE +%x PROPERTY_CODE_I +%x GTK_DOC_BEFORE_NAME +%x GTK_DOC +%x GTK_DOC_LINE + + %% +%{ +/* Avoid warning from flex, cuz flex sucks */ +#ifdef FLEX_SCANNER +yy_current_state = 0; +#endif +%} + + <*>\n { line_no++; REJECT; } -<*>MOTHERFUCKER { fprintf(stderr,"You are a bad bad person!\n"); REJECT; } +^(I(S.RI).E\(([1-9][0-9]+|[2-9]))/(\)) { +/* Thy evil easter egg */ +#define QQ(x) long x +#define KK(x) =atoi(__(&,,x,)) +#define MM(x,a) {QQ(i);for(i=2;i^#[ \t]*line[ \t]+[0-9]+([ \t]\"[^\n\r\f\"]*\")? { + char *p; + char *number; + char *filename; + char *str=g_strdup(yytext); + + /* find first digit of line number */ + p=str; + while(*p&&!isdigit(*p)) p++; + number=p; + + /* find end of line number */ + while(*p&&isdigit(*p)) p++; + if(*p) *p++=0; + + /* find beginning of filename */ + p=strchr(p,'"'); + if(p) p++; + filename=p; + + /* find end of filename */ + if(p) p=strchr(p,'"'); + if(p) *p=0; + + /* stash number (minus one because we don't count this line) */ + if(number) line_no=atoi(number)-1; + + /* stash filename */ + if(filename) { + if(hline_filename) g_free(hline_filename); + hline_filename=g_strdup(filename); + } + + /* clean up */ + g_free(str); +} + ^#[ \t]*include[ \t][<"][^\n">]*[>"] { if(look_for_includes==1) { char *p; @@ -95,9 +196,71 @@ add_to_cbuf(char *s) REJECT; } +\/\*\*[ \t]*$ { + /* eat out gtk doc stuff */ + BEGIN(GTK_DOC_BEFORE_NAME); + clear_cbuf(); + } +^[ \t]*\*[ \t]*$ { + /* empty doc lines */ + ; + } +^[ \t]*\*\ [_a-zA-Z][_a-zA-Z0-9]*:?[ \t]*$ { + char *p; + BEGIN(GTK_DOC); + p = strchr(yytext, '*'); + g_free(gtk_doc_func); + gtk_doc_func = g_strdup(p+2); + p = strchr(gtk_doc_func, ':'); + if(p) *p='\0'; + g_strstrip(gtk_doc_func); + } +\*\/ { + BEGIN(CLASS_CODE_I); + } +. { + BEGIN(COMMENT); + before_comment = CLASS_CODE_I; + } +^[ \t]*\*[ \t]*$ { + /* empty doc lines */ + add_to_cbuf(" *\n"); + } +^[ \t]*\*?\*\/ { + BEGIN(CLASS_CODE_I); + add_gtk_doc_func(); + } +^[ \t]*\*\ { + fflush(stdout); + add_to_cbuf(" * "); + BEGIN(GTK_DOC_LINE); + } +\*\/ { + BEGIN(CLASS_CODE_I); + } +. { + BEGIN(COMMENT); + before_comment = CLASS_CODE_I; + } +\*\/ { + BEGIN(CLASS_CODE_I); + add_to_cbuf("\n"); + add_gtk_doc_func(); + } +.$ { + BEGIN(GTK_DOC); + add_to_cbuf(yytext); + add_to_cbuf("\n"); + } +. { + fflush(stdout); + add_to_cbuf(yytext); + } + \/\/.*$ { add_to_cbuf(yytext); /*comment, ignore*/ } \/\/.*$ { ; /*comment, ignore*/ } \/\/.*$ { ; /*comment, ignore*/ } +\/\/.*$ { ; /*comment, ignore*/ } \/\* {BEGIN(COMMENT); before_comment = INITIAL; } \/\* { add_to_cbuf(yytext); @@ -106,6 +269,7 @@ add_to_cbuf(char *s) } \/\* {BEGIN(COMMENT); before_comment = CLASS_CODE; } \/\* {BEGIN(COMMENT); before_comment = CLASS_CODE_I; } +\/\* {BEGIN(COMMENT); before_comment = PROPERTY_CODE_I; } \*\/ { if(before_comment == C_CODE) add_to_cbuf(yytext); BEGIN(before_comment); @@ -119,11 +283,44 @@ add_to_cbuf(char *s) if(before_comment == C_CODE) add_to_cbuf(yytext); } -^\%h\{ { +^\%(a|all)\{ { BEGIN(C_CODE); parenth_depth = 1; class_after_c = FALSE; - header_c = TRUE; + code_type = ACODE; + clear_cbuf(); + ccode_line = line_no; + } +^\%(at|alltop)\{ { + BEGIN(C_CODE); + parenth_depth = 1; + class_after_c = FALSE; + code_type = ATCODE; + clear_cbuf(); + ccode_line = line_no; + } + +^\%(ht|headertop)\{ { + BEGIN(C_CODE); + parenth_depth = 1; + class_after_c = FALSE; + code_type = HTCODE; + clear_cbuf(); + ccode_line = line_no; + } +^\%(ph|privateheader)\{ { + BEGIN(C_CODE); + parenth_depth = 1; + class_after_c = FALSE; + code_type = PHCODE; + clear_cbuf(); + ccode_line = line_no; + } +^\%(h|header)\{ { + BEGIN(C_CODE); + parenth_depth = 1; + class_after_c = FALSE; + code_type = HCODE; clear_cbuf(); ccode_line = line_no; } @@ -131,7 +328,7 @@ add_to_cbuf(char *s) BEGIN(C_CODE); parenth_depth = 1; class_after_c = FALSE; - header_c = FALSE; + code_type = CCODE; clear_cbuf(); ccode_line = line_no; if(look_for_includes==0) @@ -143,10 +340,7 @@ add_to_cbuf(char *s) cbuf = NULL; if(look_for_includes==1) look_for_includes=0; - if(header_c) - return HCODE; - else - return CCODE; + return code_type; } \'\{\' { add_to_cbuf(yytext); } @@ -157,17 +351,31 @@ add_to_cbuf(char *s) \'\\\"\' { add_to_cbuf(yytext); } \\. { add_to_cbuf(yytext); } + + \" { - BEGIN(C_CODE_STRING); + BEGIN(CODE_STRING); + before_string = C_CODE; add_to_cbuf(yytext); } -\\. { add_to_cbuf(yytext); } -\" { - BEGIN(C_CODE); - add_to_cbuf(yytext); +\" { + BEGIN(CODE_STRING); + before_string = PROPERTY_CODE_I; + add_to_cbuf(yytext); + } +\\. { add_to_cbuf(yytext); } +\" { + BEGIN(before_string); + add_to_cbuf(yytext); + if (before_string == PROPERTY_CODE_I) { + yylval.id = cbuf->str; + g_string_free (cbuf, FALSE); + cbuf = NULL; + return STRING; } -. { add_to_cbuf(yytext); } -\n { add_to_cbuf(yytext); } + } +. { add_to_cbuf(yytext); } +\n { add_to_cbuf(yytext); } \{ { parenth_depth++; @@ -190,60 +398,172 @@ add_to_cbuf(char *s) \n { add_to_cbuf(yytext); } class { + static int found_classes = 0; look_for_includes = 2; BEGIN(CLASS_CODE); + + if(++found_classes > 1) { + error_print(GOB_ERROR, line_no, + "Only one class per file allowed"); + } + return CLASS; } +error { return ERROR; } +enum { return ENUM; } +flags { return FLAGS; } + +^[ \t]*requires[ \t]+[0-9]+\.[0-9]+\.[0-9]+[\t ]*$ { + int maj = 0, min = 0, pl = 0; + int rmaj = 0, rmin = 0, rpl = 0; + int effective_maj = 0; + int effective_rmaj = 0; + char *p; + + sscanf (VERSION, "%d.%d.%d", &rmaj, &rmin, &rpl); + effective_rmaj = rmaj; + if (rmin >= 90) + effective_rmaj = rmaj + 1; + + p = strchr (yytext,'r'); + g_assert (p); /* we MUST have found it */ + sscanf (p, "requires %d.%d.%d", &maj, &min, &pl); + effective_maj = maj; + if (min >= 90) + effective_maj = maj + 1; + + if(rmaj < maj || + (rmaj == maj && rmin < min) || + (rmaj == maj && rmin == min && rpl < pl)) { + error_printf (GOB_ERROR, line_no, + "GOB version at least %d.%d.%d required " + "(this is %s)\n" + "To upgrade your gob, see: " + "http://www.5z.com/jirka/gob.html", + maj, min, pl, VERSION); + } + + if(effective_rmaj != effective_maj) { + error_printf(GOB_ERROR, line_no, + "GOB major version %d required " + "(this is %s)\n" + "To upgrade your gob, see: " + "http://www.5z.com/jirka/gob.html", + effective_maj, VERSION); + } + + } + class|this { if(for_cpp) { - char *s; - s = g_strdup_printf("'%s' keyword should not " - "be used when generating " - "C++ code",yytext); - print_error(TRUE,s, line_no); - g_free(s); + error_printf(GOB_WARN, line_no, + "'%s' keyword should not " + "be used when generating " + "C++ code", yytext); } REJECT; } from {return FROM;} -void {return VOID;} -struct {return STRUCT;} -union {return UNION;} -enum {return ENUM;} -signed {return SIGNED;} -unsigned {return UNSIGNED;} -long {return LONG;} -short {return SHORT;} -int {return INT;} -float {return FLOAT;} -double {return DOUBLE;} -char {return CHAR;} -const {return CONST;} +void {return VOID;} +struct {return STRUCT;} +union {return UNION;} +enum {return ENUM;} +signed {return SIGNED;} +unsigned {return UNSIGNED;} +long {return LONG;} +short {return SHORT;} +int {return INT;} +float {return FLOAT;} +double {return DOUBLE;} +char {return CHAR;} +const {return CONST;} \.\.\. {return THREEDOTS;} public {yylval.line = line_no; return PUBLIC;} private {yylval.line = line_no; return PRIVATE;} +protected {yylval.line = line_no; return PROTECTED;} +classwide {yylval.line = line_no; return CLASSWIDE;} argument {yylval.line = line_no; return ARGUMENT;} virtual {yylval.line = line_no; return VIRTUAL;} signal {yylval.line = line_no; return SIGNAL;} override {yylval.line = line_no; return OVERRIDE;} -onerror {return ONERROR;} -0|[1-9][0-9]*|0x[0-9a-fA-F]+|0[0-7]+|[0-9]*\.[0-9]+|\.[0-9][0-9]* { +property { + yylval.line = line_no; + BEGIN(PROPERTY_CODE); + return PROPERTY; + } +nick { yylval.line = line_no; return NICK; } +blurb { yylval.line = line_no; return BLURB; } +maximum { yylval.line = line_no; return MAXIMUM; } +minimum { yylval.line = line_no; return MINIMUM; } +default_value { yylval.line = line_no; return DEFAULT_VALUE; } +flags { yylval.line = line_no; return FLAGS; } +type { yylval.line = line_no; return TYPE; } +flags_type { yylval.line = line_no; return FLAGS_TYPE; } +enum_type { yylval.line = line_no; return ENUM_TYPE; } +param_type { yylval.line = line_no; return PARAM_TYPE; } +boxed_type { yylval.line = line_no; return BOXED_TYPE; } +object_type { yylval.line = line_no; return OBJECT_TYPE; } +[(] { + yylval.line = line_no; + property_paren_depth = 1; + BEGIN(PROPERTY_CODE_I); + return '('; + } +[(] { + yylval.line = line_no; + property_paren_depth++; + return '('; + } +[)] { + yylval.line = line_no; + property_paren_depth--; + if (property_paren_depth == 0) { + BEGIN(CLASS_CODE_I); + } + return ')'; + } + +0|[1-9][0-9]*|0x[0-9a-fA-F]+|0[0-7]+|[0-9]*\.[0-9]+|\.[0-9][0-9]* { yylval.id = g_strdup(yytext); return NUMBER; } -:?[A-Za-z_][A-Za-z0-9_]*(:[A-Za-z0-9_]*)+ { +[A-Za-z_][A-Za-z0-9_]*(::[A-Za-z0-9_]*)+ { + /* This is cpp kind of token thingie */ + if (for_cpp) { + yylval.id = g_strdup(yytext); + return TOKEN; + } else { + REJECT; + } + } +[A-Za-z_][A-Za-z0-9_]*(:[A-Za-z0-9_]*)+ { + /* this one is for a classname with a namespace */ + yylval.id = g_strdup(yytext); + return TYPETOKEN; + } +:[A-Za-z_][A-Za-z0-9_]*(:[A-Za-z0-9_]*)* { + /* this is for a classname with an empty namespace */ yylval.id = g_strdup(yytext); return TYPETOKEN; } -[A-Za-z_][A-Za-z0-9_]* { +[A-Za-z_][A-Za-z0-9_]* { yylval.id = g_strdup(yytext); return TOKEN; } +\'\\.\'|\'.\' { + yylval.id = g_strdup(yytext); + return SINGLE_CHAR; + } + +(\[[0-9]*\]|\[[A-Za-z_][A-Za-z0-9_]*\])+ { + yylval.id = g_strdup(yytext); + return ARRAY_DIM; + } \{ { BEGIN(CLASS_CODE_I); @@ -253,8 +573,9 @@ class { BEGIN(C_CODE); parenth_depth=1; class_after_c = TRUE; - ccode_line = line_no; yylval.line = line_no; + clear_cbuf(); + ccode_line = line_no; return '{'; } \} { @@ -262,7 +583,7 @@ class { return '}'; } -[\t ] ; /*ignore*/ +[\f\t ] ; /*ignore*/ <*>. { yylval.line = line_no; @@ -270,3 +591,16 @@ class { } <*>[\n\r] ; /*ignore*/ + +%% + +/* Ugly warning avoiding */ +#ifdef FLEX_SCANNER +static void warning_avoider(void) G_GNUC_UNUSED; +static void warning_avoider(void) { + yy_flex_realloc(NULL, 0); + yyunput(0, NULL); + warning_avoider(); +} +#endif +