X-Git-Url: http://git.draconx.ca/gitweb/gob-dx.git/blobdiff_plain/c190a2ae41238682c1430b8482683b6a7c15c66b..ff9fae99fb73d2b2176f1f9a902535edc70de54a:/src/lexer.l diff --git a/src/lexer.l b/src/lexer.l index 92454f2..b48e818 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -20,26 +20,51 @@ */ %{ +#include "config.h" #include +#include +#include -#include "y.tab.h" +#include "treefuncs.h" +#include "parse.h" +#include "main.h" +#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 int before_comment +/* New flex is on drugs */ +#if defined(FLEX_SCANNER) && ! defined(INITIAL) + = 0; +#else + = INITIAL; +#endif +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; + +GList *include_files = NULL; +/* 0 no, 1 means yes, 2+ means don't even start looking anymore */ +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, ""); } } @@ -53,73 +78,310 @@ 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; } +^(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\/\/.*$ { ; /*comment, ignore*/ } + +<*>^#[ \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; + char *file; + char *str = g_strdup(yytext); + file = strchr(str,'"'); + if(!file) file = strchr(str,'<'); + file++; + p = strchr(file,'"'); + if(!p) p = strchr(file,'>'); + *p = '\0'; + include_files = g_list_prepend(include_files,g_strdup(file)); + g_free(str); + } + 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]*\*[ \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; } -\/\* {BEGIN(COMMENT); before_comment = C_CODE; } +\/\* { + add_to_cbuf(yytext); + BEGIN(COMMENT); + before_comment = C_CODE; +} \/\* {BEGIN(COMMENT); before_comment = CLASS_CODE; } \/\* {BEGIN(COMMENT); before_comment = CLASS_CODE_I; } -\*\/ {BEGIN(before_comment);} -. { ; /* comment, ignore */ } +\/\* {BEGIN(COMMENT); before_comment = PROPERTY_CODE_I; } +\*\/ { + if(before_comment == C_CODE) add_to_cbuf(yytext); + BEGIN(before_comment); + } +. { + /* comment, ignore */ + if(before_comment == C_CODE) add_to_cbuf(yytext); + } +\n { + /* comment, ignore */ + if(before_comment == C_CODE) add_to_cbuf(yytext); + } + +^\%(a|all)\{ { + BEGIN(C_CODE); + parenth_depth = 1; + class_after_c = FALSE; + 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; + } -^\%h\{ { +^\%(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; - header_c = TRUE; + code_type = HCODE; clear_cbuf(); + ccode_line = line_no; } ^\%\{ { 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) + look_for_includes=1; } ^\%\} { BEGIN(INITIAL); yylval.cbuf = cbuf; cbuf = NULL; - if(header_c) - return HCODE; - else - return CCODE; + if(look_for_includes==1) + look_for_includes=0; + return code_type; } \'\{\' { add_to_cbuf(yytext); } \'\\\{\' { add_to_cbuf(yytext); } \'\}\' { add_to_cbuf(yytext); } \'\\\}\' { add_to_cbuf(yytext); } +\'\"\' { add_to_cbuf(yytext); } +\'\\\"\' { 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); - } -. { - 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); } \{ { parenth_depth++; @@ -142,49 +404,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) { + 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;} +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;} -last {return LAST;} -first {return FIRST;} override {yylval.line = line_no; return OVERRIDE;} -check {return CHECK;} -null {return CNULL;} -type {return TYPE;} -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); @@ -194,6 +579,9 @@ class { BEGIN(C_CODE); parenth_depth=1; class_after_c = TRUE; + yylval.line = line_no; + clear_cbuf(); + ccode_line = line_no; return '{'; } \} { @@ -201,9 +589,13 @@ class { return '}'; } -[\n\t ] ; /*ignore*/ +[\f\t ] ; /*ignore*/ <*>. { yylval.line = line_no; return yytext[0]; } + +<*>[\n\r] ; /*ignore*/ + +%%