%{ #include #include #include "AppHdr.h" #include "l_defs.h" #include "libutil.h" #include "mapdef.h" #include "maps.h" #include "stuff.h" #define YYERROR_VERBOSE 1 int yylex(); extern int yylineno; void yyerror(const char *e) { if (strstr(e, lc_desfile.c_str()) == e) fprintf(stderr, "%s\n", e); else fprintf(stderr, "%s:%d: %s\n", lc_desfile.c_str(), yylineno, e); // Bail bail bail. end(1); } level_range set_range(const char *s, int start, int end) { try { lc_range.set(s, start, end); } catch (const std::string &err) { yyerror(err.c_str()); } return (lc_range); } %} %union { int i; const char *text; raw_range range; } /* Two harmless shift/reduce conflicts */ %expect 2 %token DEFAULT_DEPTH SHUFFLE SUBST TAGS KFEAT KITEM KMONS KMASK KPROP %token NAME DEPTH ORIENT PLACE CHANCE WEIGHT MONS ITEM MARKER COLOUR %token PRELUDE MAIN VALIDATE VETO NSUBST WELCOME LFLAGS BFLAGS %token LFLOORCOL LROCKCOL LFLOORTILE LROCKTILE FTILE RTILE TILE SUBVAULT %token COMMA COLON PERC INTEGER CHARACTER %token STRING MAP_LINE MONSTER_NAME ITEM_INFO %token LUA_LINE %% file : definitions { } ; definitions : /* empty */ {} | definitions definition {} ; definition : def {} | level {} ; error_seq : CHARACTER { yyerror("Unexpected character sequence."); } ; def : defdepth {} | global_lua {} ; defdepth : DEFAULT_DEPTH STRING { dgn_reset_default_depth(); std::string err = dgn_set_default_depth($2); if (!err.empty()) yyerror(make_stringf("Bad default-depth: %s (%s)", $2, err.c_str()).c_str()); } ; level : name map_specs { lc_map.set_file(lc_desfile); if (lc_run_global_prelude && !lc_global_prelude.empty()) { lc_global_prelude.set_file(lc_desfile); lc_run_global_prelude = false; if (lc_global_prelude.load_call(dlua, NULL)) yyerror( lc_global_prelude.orig_error().c_str() ); } std::string err = lc_map.validate_map_def(); if (!err.empty()) yyerror(err.c_str()); if (!lc_map.has_depth() && !lc_default_depths.empty()) lc_map.add_depths(lc_default_depths.begin(), lc_default_depths.end()); add_parsed_map(lc_map); } ; map_specs : /* nothing */ { } | map_specs map_spec { } ; map_spec : metaline { } | map_def { } ; name : NAME STRING { lc_map.init(); lc_map.name = $2; map_load_info_t::const_iterator i = lc_loaded_maps.find($2); if (i != lc_loaded_maps.end()) { yyerror( make_stringf( "Map named '%s' already loaded at %s:%d", $2, i->second.filename.c_str(), i->second.lineno).c_str() ); } lc_map.place_loaded_from = map_file_place(lc_desfile, yylineno); lc_loaded_maps[$2] = lc_map.place_loaded_from; } ; metaline : place | depth | chance | weight | orientation | welcome | mons | items | marker | subst | nsubst | colour | lfloorcol | lrockcol | lfloortile | lrocktile | ftile | rtile | tile | shuffle | tags | lflags | bflags | kfeat | kitem | kmons | kmask | kprop | subvault | main_lua | prelude_lua | validate_lua | veto_lua | error_seq {} ; global_lua : MAIN global_lua_lines { } global_lua_lines : /* empty */ { } | global_lua_lines global_lua_line { } ; global_lua_line : LUA_LINE { lc_global_prelude.add(yylineno, $1); } main_lua : MAIN main_lua_lines { } main_lua_lines : /* empty */ { } | main_lua_lines main_lua_line { } ; main_lua_line : LUA_LINE { lc_map.main.add(yylineno, $1); } validate_lua : VALIDATE validate_lua_lines { } validate_lua_lines : /* empty */ { } | validate_lua_lines validate_lua_line { } ; validate_lua_line : LUA_LINE { lc_map.validate.add(yylineno, $1); } veto_lua : VETO veto_lua_lines { } veto_lua_lines : /* empty */ { } | veto_lua_lines veto_lua_line { } ; veto_lua_line : LUA_LINE { lc_map.veto.add(yylineno, $1); } prelude_lua : PRELUDE prelude_lua_lines { } prelude_lua_lines : /* empty */ { } | prelude_lua_lines prelude_lua_line { } ; prelude_lua_line : LUA_LINE { lc_map.prelude.add(yylineno, $1); } kfeat : KFEAT { } | KFEAT STRING { lc_map.main.add( yylineno, make_stringf("kfeat(\"%s\")", quote_lua_string($2).c_str())); } kmons : KMONS { } | KMONS STRING { lc_map.main.add( yylineno, make_stringf("kmons(\"%s\")", quote_lua_string($2).c_str())); } kitem : KITEM { } | KITEM STRING { lc_map.main.add( yylineno, make_stringf("kitem(\"%s\")", quote_lua_string($2).c_str())); } kmask : KMASK { } | KMASK STRING { lc_map.main.add( yylineno, make_stringf("kmask(\"%s\")", quote_lua_string($2).c_str())); } kprop : KPROP { } | KPROP STRING { lc_map.main.add( yylineno, make_stringf("kprop(\"%s\")", quote_lua_string($2).c_str())); } shuffle : SHUFFLE shuffle_specifiers {} ; shuffle_specifiers : shuffle_spec | shuffle_specifiers COMMA shuffle_spec ; shuffle_spec : ITEM_INFO { lc_map.main.add( yylineno, make_stringf("shuffle(\"%s\")", quote_lua_string($1).c_str())); } tags : TAGS tagstrings {} ; tagstrings : /* empty */ | tagstrings tagstring ; tagstring : STRING { lc_map.main.add( yylineno, make_stringf("tags(\"%s\")", quote_lua_string($1).c_str())); } ; lflags : LFLAGS STRING { lc_map.main.add( yylineno, make_stringf("lflags(\"%s\")", quote_lua_string($2).c_str())); } ; bflags : BFLAGS STRING { lc_map.main.add( yylineno, make_stringf("bflags(\"%s\")", quote_lua_string($2).c_str())); } ; marker : MARKER STRING { std::string key, arg; int sep(0); const std::string err = mapdef_split_key_item($2, &key, &sep, &arg); if (!err.empty()) yyerror(err.c_str()); // Special treatment for Lua markers. if (arg.find("lua:") == 0) { arg = arg.substr(4); lc_map.main.add( yylineno, make_stringf("lua_marker(\"%s\", function () " " return %s " "end)", quote_lua_string(key).c_str(), arg.c_str())); } else { lc_map.main.add( yylineno, make_stringf("marker(\"%s\")", quote_lua_string($2).c_str())); } } ; colour : COLOUR colour_specifiers { } ; lfloorcol : LFLOORCOL { } | LFLOORCOL STRING { lc_map.main.add( yylineno, make_stringf("lfloorcol(\"%s\")", quote_lua_string($2).c_str())); } lrockcol : LROCKCOL { } | LROCKCOL STRING { lc_map.main.add( yylineno, make_stringf("lrockcol(\"%s\")", quote_lua_string($2).c_str())); } lfloortile : LFLOORTILE { } | LFLOORTILE STRING { lc_map.main.add( yylineno, make_stringf("lfloortile(\"%s\")", quote_lua_string($2).c_str())); } lrocktile : LROCKTILE { } | LROCKTILE STRING { lc_map.main.add( yylineno, make_stringf("lrocktile(\"%s\")", quote_lua_string($2).c_str())); } ftile : FTILE ftile_specifiers ; ftile_specifiers: ftile_specifier | ftile_specifiers COMMA ftile_specifier ; ftile_specifier : ITEM_INFO { lc_map.main.add( yylineno, make_stringf("ftile(\"%s\")", quote_lua_string($1).c_str())); } ; rtile : RTILE rtile_specifiers ; rtile_specifiers: rtile_specifier | rtile_specifiers COMMA rtile_specifier ; rtile_specifier : ITEM_INFO { lc_map.main.add( yylineno, make_stringf("rtile(\"%s\")", quote_lua_string($1).c_str())); } ; tile : TILE tile_specifiers ; tile_specifiers : tile_specifier | tile_specifiers COMMA tile_specifier ; tile_specifier : ITEM_INFO { lc_map.main.add( yylineno, make_stringf("tile(\"%s\")", quote_lua_string($1).c_str())); } ; colour_specifiers : colour_specifier { } | colour_specifiers COMMA colour_specifier { } ; colour_specifier : ITEM_INFO { lc_map.main.add( yylineno, make_stringf("colour(\"%s\")", quote_lua_string($1).c_str())); } ; nsubst : NSUBST nsubst_specifiers { } ; nsubst_specifiers : nsubst_spec { } | nsubst_specifiers COMMA nsubst_spec { } ; nsubst_spec : ITEM_INFO { lc_map.main.add( yylineno, make_stringf("nsubst(\"%s\")", quote_lua_string($1).c_str())); } ; subst : SUBST subst_specifiers { } ; subst_specifiers : subst_spec | subst_spec COMMA subst_specifiers ; subst_spec : ITEM_INFO { lc_map.main.add( yylineno, make_stringf("subst(\"%s\")", quote_lua_string($1).c_str())); } ; items : ITEM {} | ITEM item_specifiers {} ; item_specifiers : item_specifiers COMMA item_specifier | item_specifier ; item_specifier : ITEM_INFO { lc_map.main.add( yylineno, make_stringf("item(\"%s\")", quote_lua_string($1).c_str())); } mons : MONS {} | MONS mnames {} ; mnames : mname COMMA mnames | mname ; mname : MONSTER_NAME { lc_map.main.add( yylineno, make_stringf("mons(\"%s\")", quote_lua_string($1).c_str())); } ; place : PLACE STRING { lc_map.main.add( yylineno, make_stringf("place(\"%s\")", quote_lua_string($2).c_str())); } ; depth : DEPTH {} | DEPTH STRING { lc_map.main.add( yylineno, make_stringf("depth(\"%s\")", quote_lua_string($2).c_str())); } ; chance : CHANCE INTEGER COLON INTEGER PERC { lc_map.main.add( yylineno, make_stringf("chance(%d, %d)", $2, $4 * 100)); } | CHANCE INTEGER COLON INTEGER { lc_map.main.add( yylineno, make_stringf("chance(%d, %d)", $2, $4)); } | CHANCE INTEGER PERC { lc_map.main.add( yylineno, make_stringf("chance(0, %d)", $2 * 100)); } | CHANCE INTEGER { lc_map.main.add( yylineno, make_stringf("chance(0, %d)", $2)); } ; weight : WEIGHT INTEGER { lc_map.main.add( yylineno, make_stringf("weight(%d)", $2)); } ; orientation : ORIENT {} | ORIENT STRING { lc_map.main.add( yylineno, make_stringf("orient(\"%s\")", quote_lua_string($2).c_str())); } ; welcome : WELCOME STRING { lc_map.main.add( yylineno, make_stringf("welcome(\"%s\")", quote_lua_string($2).c_str())); } ; map_def : map_lines ; map_lines : map_lines map_line | map_line ; map_line : MAP_LINE { lc_map.mapchunk.add( yylineno, make_stringf("map(\"%s\")", quote_lua_string($1).c_str())); } ; subvault : SUBVAULT subvault_specifiers ; subvault_specifiers: subvault_specifier | subvault_specifiers COMMA subvault_specifier ; subvault_specifier : STRING { lc_map.main.add( yylineno, make_stringf("subvault(\"%s\")", quote_lua_string($1).c_str())); } ; %%