%{ #include #include #include "AppHdr.h" #include "clua.h" #include "libutil.h" #include "luadgn.h" #include "mapdef.h" #include "maps.h" #include "stuff.h" #define YYERROR_VERBOSE 1 int yylex(); extern int yylineno; static bool start_marker_segment = false; 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 %token NAME DEPTH ORIENT PLACE CHANCE MONS ITEM MARKER COLOUR %token PRELUDE MAIN VALIDATE VETO NSUBST WELCOME LFLAGS BFLAGS %token FLOORCOL ROCKCOL %token COMMA 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 | orientation | welcome | mons | items | marker | subst | nsubst | colour | floorcol | rockcol | shuffle | tags | lflags | bflags | kfeat | kitem | kmons | kmask | 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())); } 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 { lc_map.main.add(yylineno, "marker("); start_marker_segment = true; } marker_spec { lc_map.main.add(yylineno, ")"); } ; marker_spec : mspec_segments mspec_segments : /* nothing */ | mspec_segments mspec_segment ; mspec_segment : STRING { lc_map.main.add( yylineno, make_stringf( "%s\"%s\"", start_marker_segment? "" : " .. ", quote_lua_string($1).c_str())); start_marker_segment = false; } ; colour : COLOUR colour_specifiers { } ; floorcol : FLOORCOL { } | FLOORCOL STRING { lc_map.main.add( yylineno, make_stringf("floor_colour(\"%s\")", quote_lua_string($2).c_str())); } rockcol : ROCKCOL { } | ROCKCOL STRING { lc_map.main.add( yylineno, make_stringf("rock_colour(\"%s\")", quote_lua_string($2).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 { lc_map.main.add( yylineno, make_stringf("chance(\"%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.main.add( yylineno, make_stringf("map(\"%s\")", quote_lua_string($1).c_str())); } ; %%