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
|
#ifndef _INCLUDED_RULES_
#define _INCLUDED_RULES_
#include <iostream>
#include <vector>
#include <set>
#include <string>
#include <algorithm>
#include <unordered_map>
#include "../block/block.h"
#include "../terminal/terminal.h"
#include "../nonterminal/nonterminal.h"
#include "../production/production.h"
#include "../symbol/symbol.h"
// A Rule contains the information about a rule.
// Its number, and a vector of Alternatives. an Alternative is a vector of
// iterators into the symbol table
class Rules
{
bool d_defaultAction; // last action was default action:
// requires line update at the next
// rule definition
public:
// For each rule, maintain a record of file/line combinations
// indicating where the rule was first seen. This allows me to
// generate warnings when a rule is defined as full rule
// definitions rather than as alternatives. There's nothing
// inherently wrong with that, but it may also be a typo causing
// unexpected conflicts
using FileInfo = std::pair<std::string, size_t>;
//FBB: 20160412 - see also sethiddenaction.cc for the use
// of the 90000 line number flag that was used to flag
// a hidden action. Apparently it was nowhere used
// so I decided not to use it anymore.
private:
using NFileInfoMap =
std::unordered_map<NonTerminal const *, FileInfo>;
Terminal::Vector d_terminal; // the vector holding information
// about defined terminal symbols
NonTerminal::Vector d_nonTerminal; // the vector holding information
// about defined nonterminals
NFileInfoMap d_location; // the map holding information
// about initial rule locations
NonTerminal *d_currentRule; // Pointer to the N currently
// processed. Initially 0
std::string d_startRule; // name of the startrule
Production::Vector d_production; // the vector holding information
// about all productions
// productions hold Symbol
// elements, they contain
// information about type and
// index of their elements in the
// (non)terminal vectors
Production *d_currentProduction; // currently processed production
// rule (pointer to a Production
// also in d_production)
static size_t s_acceptProductionNr; // index in d_production of the
// accept rule
static size_t s_nExpectedConflicts; // how many conflicts to expect?
static Terminal s_errorTerminal; // predefined 'error' terminal
static Terminal s_eofTerminal; // predefined eof terminal
static Symbol *s_startSymbol; // derived from the initial N or
// from the N defined as the
// star tsymbol by
// augmentGrammar().
static size_t s_lastLineNr; // last received line nr, used by
// setHiddenAction()
public:
Rules(); // f
static void setExpectedConflicts(size_t value); // f
static Terminal const *eofTerminal(); // f
static Terminal const *errorTerminal(); // f
static size_t acceptProductionNr(); // f
static size_t expectedConflicts(); // f
void clearLocations(); // clear d_location // f
Terminal *insert(Terminal *terminal, std::string const &literal); // 1
NonTerminal *insert(NonTerminal *nonTerminal); // 2
void addElement(Symbol *symbol);
// add the symbol as the next element of the
// rule-production that's currently being defined.
void updateDefaultActionLineNr(size_t lineNr);
void addProduction(size_t lineNr);
// add a new production to the set of productions of the
// rule currently being defined
bool newRule(NonTerminal *nonTerminal, std::string const &source,
size_t lineNr);
// add a new rule. If startrule has not
// yet been set, define this rule as the startrule.
// return true if a really new rule was added, rather than
// expanding a rule defined earlier.
void assignNonTerminalNumbers();
void augmentGrammar(Symbol *start);
Production const &lastProduction() const; // f
FileInfo const &fileInfo(NonTerminal const *nt) const; // f
// return the FileInfo of the
// first definition of rule `nt'
std::string const &name() const; // return the name of the // f
// currently defined rule
std::string const &sType() const; // return the value type // f
// associated with the
// currently defined rule.
std::string const &sType(size_t idx) const; // return the value type
// associated with element idx of
// the currently defined production
Symbol const *symbol(size_t idx) const; // f
// return the symbol
// associated with element idx of
// the currently defined production
// Note: symbol idx MUST exist
size_t nProductions() const; // f
size_t nElements() const; // f
void determineFirst();
bool empty() const; // true: empty production rule // f
bool hasRules() const; // f
// associate an action with the currently defined rule
// production
void setAction(Block const &block, bool defaultAction = false);
void setHiddenAction(Block const &block);
void setLastTerminalValue(size_t value); // f
void setLastPrecedence(size_t value); // f
void updatePrecedences(); // try to assign a precedence to
// productions that don't yet have a
// precedence associated to them
void setPrecedence(Terminal const *terminal);
// Set the explicit precedence of the currently defined
// production to the precedence of the given terminal.
void showFirst() const; // show the First-sets
void showTerminals() const; // show symbolic terminals and their
// values
void showRules() const; // show the rule/productions
void showUnusedTerminals() const;
void showUnusedNonTerminals() const;
void showUnusedRules() const;
void setStartRule(std::string const &start); // f
std::string const &startRule() const; // f
Production const *startProduction(); // f
static Symbol const *startSymbol() ; // f
std::vector<NonTerminal const *> const &nonTerminals() const; // f
std::vector<Terminal const *> const &terminals() const; // f
std::vector<Production const *> const &productions() const; // f
void setNonTerminalTypes();
void termToNonterm(Symbol *term, Symbol *nonTerm);
private:
static bool isTerminal(Symbol const *symbol);
static void updatePrecedence(Production *production);
};
#include "rules.f"
#endif
|