%{ #include "AppHdr.h" #include "libutil.h" #include "levcomp.h" #include "stuff.h" int yylex(); extern int yylineno; void yyerror(const char *e) { fprintf(stderr, "%s:%d: %s\n", lc_desfile.c_str(), yylineno, e); // Bail bail bail. exit(1); } %} %union { int i; const char *text; } %token BRANCHDEF BRANCH DESC DEFAULT %token DEFAULT_DEPTH SYMBOL TAGS %token NAME DEPTH ORIENT PLACE CHANCE FLAGS MONS ITEM %token ROOT_DEPTH ENTRY_MSG EXIT_MSG %token ROCK_COLOUR FLOOR_COLOUR %token ENCOMPASS FLOAT %token NORTH EAST SOUTH WEST %token NORTHEAST SOUTHEAST SOUTHWEST NORTHWEST %token LEVEL END PVAULT PMINIVAULT MONSTERS ENDMONSTERS %token CHARACTER %token NO_HMIRROR NO_VMIRROR NO_ROTATE %token PANDEMONIC %token DASH COMMA QUOTE OPAREN CPAREN %token INTEGER %type orient_name flagname %token STRING MAP_LINE MONSTER_NAME ITEM_INFO %token IDENTIFIER %% file : definitions { } ; definitions : /* empty */ {} | definition definitions {} ; definition : def {} | level {} ; def : defdepth ; defdepth : DEFAULT_DEPTH depth_range { lc_default_depth = lc_range; } ; level : name metalines map_def metalines { if (lc_map.orient == MAP_FLOAT || lc_map.is_minivault()) { if (lc_map.map.width() > GXM - MAPGEN_BORDER * 2 || lc_map.map.height() > GYM - MAPGEN_BORDER * 2) { char buf[300]; snprintf(buf, sizeof buf, "%s is too big: %dx%d - max %dx%d", lc_map.is_minivault()? "Minivault" : "Float", lc_map.map.width(), lc_map.map.height(), GXM - MAPGEN_BORDER * 2, GYM - MAPGEN_BORDER * 2); yyerror(buf); } } else { if (lc_map.map.width() > GXM || lc_map.map.height() > GYM) { char buf[300]; snprintf(buf, sizeof buf, "Map is too big: %dx%d - max %dx%d", lc_map.map.width(), lc_map.map.height(), GXM, GYM); yyerror(buf); } } if (lc_map.map.height() == 0) yyerror("Must define map."); add_parsed_map( lc_map ); } ; name : NAME STRING { lc_map.init(); lc_map.depth = lc_default_depth; lc_map.name = $2; } ; metalines : /* no metadata */ | metaline metalines ; metaline : place | depth | chance | orientation | flags | mons | items | symbol | tags ; tags : TAGS tagstrings {} ; tagstrings : /* empty */ | STRING tagstrings { lc_map.tags += " "; lc_map.tags += $1; lc_map.tags += " "; } ; symbol : SYMBOL {} | SYMBOL STRING { lc_map.random_symbols = $2; } ; items : ITEM {} | ITEM item_specifiers {} ; item_specifiers : item_specifier COMMA item_specifiers | item_specifier ; item_specifier : ITEM_INFO { std::string error = lc_map.items.add_item($1); if (error.size()) { char errbuf[300]; snprintf(errbuf, sizeof errbuf, "Invalid item descriptor: '%s' (%s)", $1, error.c_str()); yyerror(errbuf); } if (lc_map.items.size() > 8) yyerror("Too many items specified (max 8)"); } mons : MONS {} | MONS mnames {} ; mnames : mname COMMA mnames | mname ; mname : MONSTER_NAME { std::string err = lc_map.mons.add_mons($1); if (!err.empty()) { char buf[300]; snprintf(buf, sizeof buf, "bad monster spec '%s' (%s)", $1, err.c_str()); yyerror(buf); } if (lc_map.mons.size() > 7) yyerror("Too many monsters specified (max 7)"); } ; place : PLACE STRING { lc_map.place = $2; } ; depth : DEPTH {} | DEPTH depth_range { lc_map.depth = lc_range; } ; depth_range : INTEGER DASH INTEGER { lc_range.set($1, $3); } | INTEGER { lc_range.set($1); } ; chance : CHANCE INTEGER { lc_map.chance = $2; } ; orientation : ORIENT {} | ORIENT orient_name { lc_map.orient = (map_section_type) $2; } ; orient_name : ENCOMPASS { $$ = MAP_ENCOMPASS; } | NORTH { $$ = MAP_NORTH; } | EAST { $$ = MAP_EAST; } | SOUTH { $$ = MAP_SOUTH; } | WEST { $$ = MAP_WEST; } | NORTHEAST { $$ = MAP_NORTHEAST; } | SOUTHEAST { $$ = MAP_SOUTHEAST; } | SOUTHWEST { $$ = MAP_SOUTHWEST; } | NORTHWEST { $$ = MAP_NORTHWEST; } | FLOAT { $$ = MAP_FLOAT; } ; flags : FLAGS flagnames {} ; flagnames : /* empty */ | flagname flagnames { switch ($1) { case NO_HMIRROR: lc_map.flags &= ~MAPF_MIRROR_HORIZONTAL; break; case NO_VMIRROR: lc_map.flags &= ~MAPF_MIRROR_VERTICAL; break; case NO_ROTATE: lc_map.flags &= ~MAPF_ROTATE; break; } } ; flagname : NO_HMIRROR { $$ = NO_HMIRROR; } | NO_VMIRROR { $$ = NO_VMIRROR; } | NO_ROTATE { $$ = NO_ROTATE; } ; map_def : map_lines ; map_lines : map_line | map_line map_lines ; map_line : MAP_LINE { lc_map.map.add_line($1); } ; %%