X-Git-Url: https://git.draconx.ca/gitweb/gob-dx.git/blobdiff_plain/f31590988781d77ff5249987801d03a986368ca2..86d4727e727a55648196205cff450c96569ec4a6:/src/lexer.l diff --git a/src/lexer.l b/src/lexer.l index 35e42cc..d33965d 100644 --- a/src/lexer.l +++ b/src/lexer.l @@ -1,5 +1,9 @@ -/* GOB C Preprocessor - * Copyright (C) 1999 the Free Software Foundation. +%top{ +/* + * GOB C Preprocessor + * Copyright (C) 1999-2000 the Free Software Foundation. + * Copyright (C) 2000 Eazel, Inc. + * Copyright (C) 2001-2011 George (Jiri) Lebl * * Author: George Lebl * @@ -18,21 +22,36 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, * USA. */ -%{ +#include +} -#include "config.h" -#include +%{ +#include #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 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; @@ -42,14 +61,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,22 +84,116 @@ 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 / error avoidings */ +#ifdef FLEX_SCANNER +int yylex(void); +int yywrap(void) { return 1; } +#endif + %} %x COMMENT %x C_CODE -%x C_CODE_STRING +%x CODE_STRING %x CLASS_CODE +%x CLASS_STRING %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]*include[ \t][<"][^\n">]*[>"] { + +<*>^#[ \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\r">]*[>"] { if(look_for_includes==1) { char *p; char *file; @@ -88,16 +203,80 @@ add_to_cbuf(char *s) file++; p = strchr(file,'"'); if(!p) p = strchr(file,'>'); - *p = '\0'; - include_files = g_list_prepend(include_files,g_strdup(file)); - g_free(str); + if (p != NULL) { + *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; } \/\* { add_to_cbuf(yytext); @@ -106,6 +285,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 +299,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; + 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; - header_c = TRUE; + code_type = HCODE; clear_cbuf(); ccode_line = line_no; } @@ -131,22 +344,37 @@ 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) + look_for_includes=1; + } +^\%(ct|ctop)\{ { + BEGIN(C_CODE); + parenth_depth = 1; + class_after_c = FALSE; + code_type = CTCODE; clear_cbuf(); ccode_line = line_no; if(look_for_includes==0) look_for_includes=1; } +^\%(ad|afterdecls)\{ { + BEGIN(C_CODE); + parenth_depth = 1; + class_after_c = FALSE; + code_type = ADCODE; + clear_cbuf(); + ccode_line = line_no; + } ^\%\} { BEGIN(INITIAL); yylval.cbuf = cbuf; 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 +385,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,76 +432,211 @@ 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;} +\" { + BEGIN(CLASS_STRING); + before_string = CLASS_CODE; + add_to_cbuf(yytext); + } +\\. { add_to_cbuf(yytext); } +\" { + BEGIN(before_string); + add_to_cbuf(yytext); + yylval.id = cbuf->str; + g_string_free (cbuf, FALSE); + cbuf = NULL; + return STRING; + } +. { add_to_cbuf(yytext); } +\n { add_to_cbuf(yytext); } -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;} +\" { + BEGIN(CLASS_STRING); + before_string = CLASS_CODE_I; + add_to_cbuf(yytext); + } + +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; } +name { yylval.line = line_no; return NAME; } +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-z_][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-z_][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]*\])+ { +(\[[0-9]*\]|\[[A-Za-z_][A-Za-z0-9_]*\])+ { + yylval.id = g_strdup(yytext); + return ARRAY_DIM; + } +:[0-9]+ { + /* cheat for bitfield */ yylval.id = g_strdup(yytext); return ARRAY_DIM; } - \{ { BEGIN(CLASS_CODE_I); return '{'; } -\{ { +\{ { 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 '{'; } \} { @@ -267,11 +644,23 @@ class { return '}'; } -[\t ] ; /*ignore*/ +[\f\t ] ; /*ignore*/ + +<*>[\n\r] ; /*ignore*/ + <*>. { yylval.line = line_no; return yytext[0]; } -<*>[\n\r] ; /*ignore*/ +^[ \t]*prealloc[ \t]+[0-9]+[ \t]*$ { + char *p; + int t; + p = strchr (yytext,'p'); + g_assert (p); /* we MUST have found it */ + sscanf (p, "prealloc %d", &t); + npreallocs=t; + } + +%%