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
|
#ifndef _INCLUDED_PRODUCTION_
#define _INCLUDED_PRODUCTION_
#include <vector>
#include <string>
#include <iosfwd>
#include <algorithm>
#include "../block/block.h"
#include "../symbol/symbol.h"
#include "../terminal/terminal.h"
// NOTE: To obtain all productions of a certain Non-Terminal, use
// NonTerminal's `productions()' member
class Production: private std::vector<Symbol *>
{
typedef std::vector<Symbol *> Inherit;
friend std::ostream &operator<<(std::ostream &out,
Production const *production);
Terminal const *d_precedence; // 0 or a pointer to some terminal
// defining this production's
// precedence (through %prec)
Block d_action; // action associated with this
// production.
Symbol const *d_nonTerminal; // pointer to the lhs nonterminal of
// this production
size_t d_nr; // production order number
// over all productions,
// starts at 1
mutable bool d_used; // true once this production has been
// used.
static size_t s_nr; // incremented at each new production
static bool s_unused; // prevents multiple 'unused
// production rules' warnings
static Production const *s_startProduction; // a pointer to the start
// production rule.
public:
using Inherit::size;
using Inherit::begin;
using Inherit::end;
using Inherit::rbegin;
using Inherit::rend;
using Inherit::push_back;
typedef std::vector<Production *> Vector;
typedef std::vector<Production const*> ConstVector;
typedef ConstVector::const_iterator ConstIter;
Production(Symbol const *nonTerminal);
Block const &action() const;
Symbol const &operator[](size_t idx) const;
Symbol const *rhs(size_t idx) const; // idx-ed symbol in the rhs
Symbol const *lhs() const;
Terminal const *precedence() const;
bool hasAction() const;
bool isEmpty() const;
size_t nr() const;
void used() const; // d_used is mutable
void setAction(Block const &block);
void setPrecedence(Terminal const *terminal);
static Production const *start();
static void insertAction(Production const *prod, std::ostream &out,
bool lineDirectives, size_t indent);
static void setStart(Production const *production);
static void termToNonterm(Production *pPtr, Symbol *terminal,
Symbol *nonTerminal);
static void unused(Production const *production);
static bool notUsed();
static bool isTerminal();
private:
Symbol *vectorIdx(size_t idx) const;
std::ostream &standard(std::ostream &out) const;
};
inline bool Production::notUsed()
{
return s_unused;
}
inline Symbol const *Production::rhs(size_t idx) const
{
return vectorIdx(idx);
}
inline Symbol const *Production::lhs() const
{
return d_nonTerminal;
}
inline size_t Production::nr() const
{
return d_nr;
}
inline void Production::used() const
{
d_used = true;
}
inline Block const &Production::action() const
{
return d_action;
}
inline bool Production::hasAction() const
{
return !d_action.empty();
}
inline bool Production::isEmpty() const
{
return empty() && d_action.empty();
}
inline Terminal const *Production::precedence() const
{
return d_precedence;
}
inline Symbol const &Production::operator[](size_t idx) const
{
return *vectorIdx(idx);
}
inline void Production::setAction(Block const &block)
{
d_action = block;
}
inline void Production::setStart(Production const *production)
{
s_startProduction = production;
}
inline Production const *Production::start()
{
return s_startProduction;
}
inline std::ostream &operator<<(std::ostream &out, Production const *prod)
{
return prod->standard(out);
}
inline bool isTerminal(Symbol const *symbol)
{
return symbol->isTerminal();
}
inline void Production::termToNonterm(Production *pPtr,
Symbol *terminal, Symbol *nonTerminal)
{
std::replace(pPtr->begin(), pPtr->end(), terminal, nonTerminal);
}
#endif
|