%{ // levcomp.lpp: // Level compiler lexer for Dungeon Crawl Stone Soup. // // Based loosely on NetHack's lev_comp.l #include #include #include #include "AppHdr.h" #include "mapdef.h" #include "levcomp.tab.h" static bool alloced = false; std::queue free_queue; static void flush_free_queue(unsigned int max_allowed) { while (free_queue.size() > max_allowed) { const char *s = free_queue.front(); free((void *) s); free_queue.pop(); } } static void add_to_queue(const char *s) { free_queue.push(s); flush_free_queue(100); } static void clean() { if (yylval.text && alloced) add_to_queue(yylval.text); yylval.text = NULL; alloced = false; } static char *copy_text(bool trim_right, int strip_trailing) { char *newstring = NULL; if ((yylval.text = newstring = strdup(yytext))) { alloced = true; char *s = NULL; if (trim_right) { s = newstring + strlen(newstring) - 1; while (isspace(*s) && s >= newstring) *s-- = 0; } if (strip_trailing) { if (!s) s = newstring + strlen(newstring) - 1; while (s >= newstring && --strip_trailing >= 0) *s-- = 0; } } return (newstring); } static void settext(bool trim_right = false, int strip_trailing = 0) { clean(); char *newstring = copy_text(trim_right, strip_trailing); yylval.text = newstring; } %} %x MAPDEF %x LUA %x LUA_ONELINER %s ARGUMENT %s MNAME %s KEYWORDS %x ITEM_LIST %x TOEOL %option yylineno %option never-interactive NSPACE [^\ \t\r\n] %% ^\s*ENDMAP[ ]* { BEGIN(INITIAL); } ^[^\r\n\t]+ { settext(true); return MAP_LINE; } ^[ ]*\r?\n return CHARACTER; # return CHARACTER; [\ ][^\ \r\n] return CHARACTER; [ ]*\r?\n ; \s*\}\}[ \t\r]*$ { BEGIN(INITIAL); } [^\r\n]+\}\}[ \t\r]*$ { settext(true, 2); BEGIN(INITIAL); return LUA_LINE; } [^\r\n]+ { settext(true); return LUA_LINE; } \r?\n ; [^\r\n]+\r?$ { settext(true); return LUA_LINE; } \r?\n { BEGIN(INITIAL); } [A-Za-z_0-9\-]+ { settext(); return STRING; } [ \t]+ ; [ \t]*\r?\n { BEGIN(INITIAL); } [^, \t\r\n][^,\r\n]*[^, \t\r\n] { settext(); return ITEM_INFO; } [^, \t\r\n] { settext(); return ITEM_INFO; } , return COMMA; [ \t]+ ; [ \t]*\r?\n { BEGIN(INITIAL); } [\ \t\r]*\n { BEGIN(INITIAL); } [^,\ \t\r\n][^,\r\n]+[^,\ \t\r\n] { settext(); return MONSTER_NAME; } , return COMMA; [ \t\r]+ ; {NSPACE}.*{NSPACE} { BEGIN(INITIAL); settext(); return STRING; } \r?\n { BEGIN(INITIAL); } .*\\[ \t\r]*$ { settext(true, 1); return STRING; } .+$ { BEGIN(INITIAL); settext(true); return STRING; } \r?\n ; ^[ \t]*#.* ; ^\s*MAP[ \t\r]*$ { BEGIN(MAPDEF); } ^[ \t]*: { BEGIN(LUA_ONELINER); return MAIN; } ^[ \t]*prelude[ \t]*\{\{ { BEGIN(LUA); return PRELUDE; } ^[ \t]*lua[ \t]*\{\{ { BEGIN(LUA); return MAIN; } ^[ \t]*\{\{ { BEGIN(LUA); return MAIN; } ^[ \t]*validate[ \t]*\{\{ { BEGIN(LUA); return VALIDATE; } ^[ \t]*veto[ \t]*\{\{ { BEGIN(LUA); return VETO; } NAME: { BEGIN(ARGUMENT); return NAME; } default-depth: { BEGIN(ARGUMENT); return DEFAULT_DEPTH; } DEPTH: { BEGIN(ARGUMENT); return DEPTH; } ORIENT: { BEGIN(ARGUMENT); return ORIENT; } PLACE: { BEGIN(ARGUMENT); return PLACE; } WELCOME: { BEGIN(ARGUMENT); return WELCOME; } CHANCE: return CHANCE; WEIGHT: return CHANCE; FLAGS: { BEGIN(KEYWORDS); return TAGS; } TAGS: { BEGIN(KEYWORDS); return TAGS; } LFLAGS: { BEGIN(ARGUMENT); return LFLAGS; } BFLAGS: { BEGIN(ARGUMENT); return BFLAGS; } SUBST: { BEGIN(ITEM_LIST); return SUBST; } NSUBST: { BEGIN(ITEM_LIST); return NSUBST; } COLOUR: { BEGIN(ITEM_LIST); return COLOUR; } FLOORCOL: { BEGIN(ARGUMENT); return FLOORCOL; } ROCKCOL: { BEGIN(ARGUMENT); return ROCKCOL; } MONS: { BEGIN(MNAME); return MONS; } ITEM: { BEGIN(ITEM_LIST); return ITEM; } MARKER: { BEGIN(TOEOL); return MARKER; } SHUFFLE: { BEGIN(ITEM_LIST); return SHUFFLE; } KFEAT: { BEGIN(ARGUMENT); return KFEAT; } KITEM: { BEGIN(ARGUMENT); return KITEM; } KMONS: { BEGIN(ARGUMENT); return KMONS; } KMASK: { BEGIN(ARGUMENT); return KMASK; } , return COMMA; [0-9]+ { clean(); yylval.i = atoi(yytext); return INTEGER; } [\ \t]+ ; \r?\n ; \r ; . return CHARACTER; %% int yywrap() { clean(); flush_free_queue(0); return 1; }