1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
|
#ifndef Parser_h_included
#define Parser_h_included
// $insert baseclass
#include "parserbase.h"
// $insert scanner.h
#include "../scanner/scanner.h"
#include <unordered_map>
class NonTerminal;
class Terminal;
class Symbol;
struct Options;
class AtDollar;
namespace FBB
{
class Mstream;
}
#undef Parser
class Parser: public ParserBase
{
// actions to taken given tokens returned by the lexical scanner
using ActionMap = std::unordered_map<size_t, void (Parser::*)()>;
using Iterator = ActionMap::iterator;
using Value = ActionMap::value_type;
using StrStrMap = std::unordered_map<std::string, std::string>;
enum SemType // s_autoTypeLable must be synchronized with this
{ // enum
SINGLE,
UNION,
POLYMORPHIC
};
static char const *s_autoTypeLabel[];
// data members that are self-explanatory are not explicitly
// described here.
FBB::Arg &d_arg;
Options &d_options;
// $insert scannerobject
Scanner d_scanner;
std::string const &d_matched;
Rules &d_rules;
Symtab d_symtab;
std::string d_expect;
std::string d_field; // %union field or %polymorphic
// Tag_ value in %type specifications
bool d_typeDirective = false;// true following %type
bool d_negativeDollarIndicesOK = false;
SemType d_semType = SINGLE; // see set{union,polymorphic}decl.cc
// ADfun: pointer to member function handling @ and $ constructions
using ADfun = bool (Parser::*)
(int nElements, Block &block, AtDollar const &atd);
// ADmap: unordered map returning a function given an
// AtDollar::Pattern
using ADmap = std::unordered_map<int, ADfun>;
ADmap *d_atDollar = &s_single;
Terminal::Association d_association;
// associations between tags (keys) and types (values) of
// polymorphic semantic values
StrStrMap d_polymorphic;
static size_t s_nHidden; // number of hidden nonterminals
static std::ostringstream s_hiddenName;
static std::string s_semanticValue; // name of the semantic value variable
// used by the generated parser
static std::string s_semanticValueStack;
// name of the semantic value stack
// used by the generated parser
static char s_locationValueStack[];
// name of the location value stack
// used by the generated parser
static char s_locationValue[];
// name of the location value variable
// used by the generated parser (@0)
static std::string s_stype; // generic semantic value for POLYMORPHIC
static std::string const s_undefined;
static ADmap s_single;
static ADmap s_union;
static ADmap s_polymorphic;
using ActionBlockInstaller = void (Parser::*)(std::string const &ruleType,
Production const &prod);
static ActionBlockInstaller s_defaultAction[2][3][3];
public:
Parser(Rules &rules);
int parse();
void cleanup(); // do cleanup following parse();
StrStrMap releasePolymorphic();
private:
void updateDefaultActionLineNr();
void checkField(std::string const &field); // see inc/typename
static void warnDefaultAction(Production const &prod);
void installDefaultAction(Production const &prod,
std::string const &rhs);
void defaultPolymorphicAction(Production const &prod);
static std::string const &nameOf(std::string const &typeName); // ih
// see s_defaultAction[] for details
static int typeIndex(std::string const &typeName); // 0: "",
// 1: s_stype
// 2: other types
// no action block is installed
void blkNop(std::string const &ruleType, Production const &prod);
// no action block + error message
void blkErr(std::string const &ruleType, Production const &prod);
// a $$ = STYPE_{} action block
void blkSTYPE(std::string const &ruleType, Production const &prod);
// a $$ = $1.get... action block
void blkAssign(std::string const &ruleType, Production const &prod);
// a $$ = $1 action block
void blkDirect(std::string const &ruleType, Production const &prod);
// with equal types: blkAssign, otherwise blkErr
void blkCheck(std::string const &ruleType, Production const &prod);
// warns that no action block is installed
void blkNopW(std::string const &ruleType, Production const &prod);
// warns and blkSTYPE
void blkSTYPEW(std::string const &ruleType, Production const &prod);
// warns and blkAssign
void blkAssignW(std::string const &ruleType, Production const &prod);
// warns and blkDirect
void blkDirectW(std::string const &ruleType, Production const &prod);
// with equal types blkAssignW, otherwise blkErr
void blkCheckW(std::string const &ruleType, Production const &prod);
std::ostream &stdWmsg(AtDollar const &atd) const;
std::ostream &stdEmsg(AtDollar const &atd) const;
void warnNegativeDollarIndices(AtDollar const &atd) const;
int indexToOffset(int idx, int nElements) const;
bool existingTag(AtDollar const &atd) const; // false and emsg if
// not an existing tag
void errNoUnionPtr(AtDollar const &atd);
bool errNoTag(int nElements, Block &block, AtDollar const &atd);
bool errIndexTooLarge(AtDollar const &atd, int nElements) const;
void warnForceLSP(size_t lineNr) const;
void warnMissingSemval() const;
void substituteBlock(int nElements, Block &block);
// replacement members (see also handleProductionElement)
// the dval*Replace return true for midRule actions,
// because that prevents the missingSemval warning.
bool dvalReplace(bool midRule, Block &block, AtDollar const &atd,
char const *suffix);
bool svsReplace(int nElements, Block &block, AtDollar const &atd,
char const *suffix);
bool dvalUnionReplace(bool midRule, Block &block, AtDollar const &atd,
char const *suffix);
bool svsUnionReplace(int nElements, Block &block, AtDollar const &atd,
char const *suffix);
bool dvalPolyReplace(bool midRule, Block &block, AtDollar const &atd,
char const *suffix);
bool svsPolyReplace(int nElements, Block &block, AtDollar const &atd,
char const *suffix);
bool svsUnionTagReplace(int nElements, Block &block, AtDollar
const &atd, char const *suffix);
bool svsPolyTagReplace(int nElements, Block &block, AtDollar
const &atd, char const *suffix);
// returns s_semanticValueStack[index]:
std::string svsElement(int nElements, int nr) const; // nr, not index!
// empty, or tag associated with a production rule's element
// requires: nr > 0
std::string const &productionTag(int nr) const; // ih
// $- and @-handlers
// @@
bool loc(int nElements, Block &block, AtDollar const &atd);
// @nr
bool locEl(int nElements, Block &block, AtDollar const &atd);
// Wrt the dval* functions below:
// 'refByScanner' means that the syntax used $$, but the scanner
// changed that into _$$. In those cases mid-action rules should issue
// warnings if the terminal has an associated type. Otherwise, an
// explicit _$$ was used and no warning needs to be issued.
// mid-rule actions (nElements < 0) should not issue missing Semval
// warnings This is realized by returning true if nElements < 0
// $$
bool dval(int nElements, Block &block, AtDollar const &atd);
bool dvalUnion(int nElements, Block &block, AtDollar const &atd);
bool dvalRefUnion(int nElements, Block &block, AtDollar const &atd);
bool dvalPoly(int nElements, Block &block, AtDollar const &atd);
// $$(
bool dvalPar(int nElements, Block &block, AtDollar const &atd);
bool dvalUnionPar(int nElements, Block &block, AtDollar const &atd);
bool dvalPolyPar(int nElements, Block &block, AtDollar const &atd);
// $$.
bool dvalMem(int nElements, Block &block, AtDollar const &atd);
bool dvalUnionMem(int nElements, Block &block, AtDollar const &atd);
bool dvalPolyMem(int nElements, Block &block, AtDollar const &atd);
// $$->
bool dvalPtr(int nElements, Block &block, AtDollar const &atd);
bool dvalUnionPtr(int nElements, Block &block, AtDollar const &atd);
bool dvalPolyPtr(int nElements, Block &block, AtDollar const &atd);
// $nr _$nr $-nr _$-nr
bool svs(int nElements, Block &block, AtDollar const &atd);
bool svsUnion(int nElements, Block &block, AtDollar const &atd);
bool svsRefUnion(int nElements, Block &block, AtDollar const &atd);
bool svsPoly(int nElements, Block &block, AtDollar const &atd);
// $nr. $-nr.
bool svsMem(int nElements, Block &block, AtDollar const &atd);
bool svsUnionMem(int nElements, Block &block, AtDollar const &atd);
bool svsPolyMem(int nElements, Block &block, AtDollar const &atd);
// $nr-> $-nr->
bool svsPtr(int nElements, Block &block, AtDollar const &atd);
bool svsUnionPtr(int nElements, Block &block, AtDollar const &atd);
bool svsPolyPtr(int nElements, Block &block, AtDollar const &atd);
// $<TAG>-nr
bool svsUnionTag(int nElements, Block &block, AtDollar const &atd);
bool svsPolyTag(int nElements, Block &block, AtDollar const &atd);
// $<TAG>-nr.
bool svsUnionTagMem(int nElements, Block &block, AtDollar const &atd);
bool svsPolyTagMem(int nElements, Block &block, AtDollar const &atd);
// $<TAG>-nr->
bool svsUnionTagPtr(int nElements, Block &block, AtDollar const &atd);
bool svsPolyTagPtr(int nElements, Block &block, AtDollar const &atd);
// ================================================================
void defaultAction() const; // ih
void constructorChecks() const; // ih
void warnTagMismatches() const; // ih
std::string warnAutoTag(bool midRule, AtDollar const &atd) const;
void addPolymorphic(std::string const &tag,
std::string const &typeSpec);
void addIncludeQuotes(std::string *target); // ensure ".." or <..>
// around target name
void checkEmptyBlocktype(); // ih
void checkFirstType();
Symbol *defineNonTerminal(std::string const &name,
std::string const &stype);
void definePathname(std::string *target);
void defineTerminal(std::string const &name, Symbol::Type type);
void defineTokenName(std::string const &name, bool hasValue);
void expectRules();
void setExpectedConflicts(); // ih
void setLocationDecl();
void setNegativeDollarIndices(); // ih
STYPE_ setPrecedence(size_t type);
void setUnionDecl();
size_t extractIndex(int *idx, size_t pos);
size_t extractType(std::string *type, size_t pos, Block &block);
STYPE_ handleProductionElements(STYPE_ &first,
STYPE_ const &second);
void handleProductionElement(STYPE_ &last);
void installAction(Block &block);
void multiplyDefined(Symbol const *sp);
void nestedBlock(Block &block); // define inner block as pseudo N
std::string nextHiddenName();
void setStart();
void setPolymorphicDecl();
void openRule(std::string const &ruleName);
void predefine(Terminal const *terminal); // Used by Parser() to
// pre-enter into d_symtab
NonTerminal *requireNonTerminal(std::string const &name);
Symbol *useSymbol();
Terminal *useTerminal();
void error(); // called on (syntax) errors
void exceptionHandler(std::exception const &exc); // ih
int lex(); // returns the next token from // ih
// the lexical scanner.
void print(); // use, e.g., d_token, d_loc // ih
// support functions for parse():
void executeAction_(int ruleNr);
void errorRecovery_();
void nextCycle_();
void nextToken_();
void print_();
// used in, e.g., handleDollar
// to obtain # elements for
// end- or mid-rule actions
static int nComponents(int nElements); // ih
};
#endif
|