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
|
#pragma once
#include "Compiler/Syntax/Production.h"
#include "Core/PODArray.h"
namespace storm {
namespace syntax {
namespace earley {
STORM_PKG(lang.bnf.earley);
class Parser;
/**
* Pointer to a state in some StateSet. Represented by two integers: the step and the index
* into that step. Null is represented by step and index being (Nat)-1.
*/
class StatePtr {
STORM_VALUE;
public:
// Create invalid state pointer.
STORM_CTOR StatePtr();
// Create to a specific state.
STORM_CTOR StatePtr(Nat step, Nat index);
// The step.
Nat step;
// Index inside that step.
Nat index;
// Compare.
inline Bool STORM_FN operator ==(const StatePtr &o) const {
return step == o.step && index == o.index;
}
inline Bool STORM_FN operator !=(const StatePtr &o) const {
return !(*this == o);
}
// Output.
void STORM_FN toS(StrBuf *to) const;
};
wostream &operator <<(wostream &to, StatePtr p);
/**
* State used during parsing (in Parser.h/cpp). Contains a location into a production, a
* step where the option was instantiated, a pointer to the previous step and optionally the
* step that was completed.
*/
class State {
STORM_VALUE;
public:
// Create.
STORM_CTOR State();
STORM_CTOR State(ProductionIter pos, Nat from);
STORM_CTOR State(ProductionIter pos, Nat from, StatePtr prev);
STORM_CTOR State(ProductionIter pos, Nat from, StatePtr prev, StatePtr completed);
// Position in the production.
ProductionIter pos;
// The step where this production was instantiated.
Nat from;
// Previous instance of this state.
StatePtr prev;
// State that completed this state. If set, this means that pos->token is a rule token.
StatePtr completed;
// Is this a valid state (ie. does it have a valid position?)
inline Bool valid() const {
return pos.valid();
}
// Get the priority for the rule associated with this state.
inline Int priority() const {
return pos.production()->priority;
}
// Get the production this state represents.
inline Production *production() const {
return pos.production();
}
// See if this state is a Rule token.
inline RuleToken *getRule() const {
Token *t = pos.token();
return t ? t->asRule() : null;
}
// See if this state is a Regex token.
inline RegexToken *getRegex() const {
Token *t = pos.token();
return t ? t->asRegex() : null;
}
// See if this state finishes a production.
inline Bool finishes(Production *p) const {
return production() == p
&& pos.end();
}
// Equality, as required by the parser. TODO: adhere to the future standard equal interface.
inline Bool STORM_FN operator ==(const State &o) const {
return pos == o.pos
&& from == o.from;
}
inline Bool STORM_FN operator !=(const State &o) const {
return !(*this == o);
}
// Output.
void STORM_FN toS(StrBuf *to) const;
};
// To string.
wostream &operator <<(wostream &to, State s);
/**
* Ordered set of states. Supports proper ordering by priority.
*/
class StateSet : public Object {
STORM_CLASS;
public:
// Create.
StateSet();
// Insert a state here if it does not exist. May alter the 'completed' member of an
// existing state to obey priority rules.
void STORM_FN push(Parser *parser, const State &state);
// Insert a new state (we will allocate it for you if neccessary)
void STORM_FN push(Parser *parser, ProductionIter pos, Nat from);
void STORM_FN push(Parser *parser, ProductionIter pos, Nat from, StatePtr prev);
void STORM_FN push(Parser *parser, ProductionIter pos, Nat from, StatePtr prev, StatePtr completed);
// Current size of this set.
inline Nat STORM_FN count() const {
if (chunks == null)
return 0;
if (chunks->filled == 0)
return 0;
nat last = Nat(chunks->filled - 1);
return last*chunkSize + Nat(chunks->v[last]->filled);
}
// Get an element in this set.
inline const State &STORM_FN operator [](Nat i) const {
GcArray<State> *chunk = chunks->v[i >> chunkBits];
return chunk->v[i & chunkMask];
}
private:
// Chunk size. Must be a power of two.
enum {
chunkBits = 5,
chunkSize = (1 << chunkBits),
chunkMask = chunkSize - 1
};
// State data. Represented as a two-level array to avoid copying.
GcArray<GcArray<State> *> *chunks;
// The GcType for arrays of State objects.
const GcType *stateArrayType;
// Size of the array to use when computing production ordering. Should be large enough
// to cover the majority of productions, otherwise we loose performance.
typedef PODArray<StatePtr, 20> StateArray;
// Ordering.
enum Order {
before,
after,
none,
};
// Compute the execution order of two states when parsed by a top-down parser.
Order execOrder(Parser *parser, const StatePtr &a, const StatePtr &b) const;
Order execOrder(Parser *parser, const State &a, const State &b) const;
// Find the 'completed' field for previous states. May contain entries representing null.
void prevCompleted(Parser *parser, const State &from, StateArray &to) const;
// Ensure we have at least 'n' chunks.
void ensure(Nat n);
};
}
}
}
|