The parser is initialized by generating a handle for
each production and adding them to every core, as
shown in Figure 10.
The addHandle procedure in Figure 9 is respon-
sible for adding a handle to a core. It also adds the
corresponding agenda entries for that handle with the
nodes that follow the core and match the symbol af-
ter the dot in the dotted production of the handle. It
should be noted that the addHandle procedure consid-
ers epsilon productions: if a production RHS symbol
is in the epsilonSymbols set, both the possibilities of
it being reduced or not by that production are consid-
ered; that is, a new handle that skips that element is
added to the same core. It should also be noted that
element are skipped iteratively, as many consecutive
RHS symbols of a production could be in the epsilon-
Symbols set.
The parsing process consists in iteratively extract-
ing entries consisting of handles and nodes from the
agenda and matching the next symbol of the RHS
of the handle production with the node. The han-
dles whose productions are successfully matched are
added to the cores following the node and the agenda
is updated with the entries that contain any of the
newly generated handles. In case all the symbols of
a production RHS match a sequence of nodes, a new
node is generated by reducing them. The new node
start index is obtained from the handle, its end posi-
tion is obtained from the last node matched, and its
symbol is the LHS symbol of the production. When
a newly generated node only has the starting core in
its preceding core set and the final core in its follow-
ing core set, and its symbol corresponds to the initial
symbol of the grammar, it is added to the parse graph
starting node set, which means that that node repre-
sents a valid parse. The pseudocode for this process
is shown in Figure 11.
The result of the chart parsing phase is an I-graph,
which the constraint enforcement phase accepts as in-
put.
The Fence chart parsing phase order of efficiency
is theoretically equivalent to existing Earley chart
parsers. That is, O(n
3
) in the general case, O(n
2
)
for unambiguous grammars, and O(n) for almost all
LR(k) grammars, being n the length of the input
string.
3.4 Constraint Enforcement Phase
The Fence constraint enforcement phase processes
the I-graph and generates an explicit parse graph (E-
graph, or just parse graph) by enforcing the con-
straints defined for the language. Nodes in the
E-graph that represent tokens are still defined as
(start, end, symbol) tuples. Nodes in the E-graph that
represent nonterminal symbols reference the list of
nodes that matched the production used to generate
those nodes. It should be noted that ambiguities, both
lexical and syntactic, are explicit in the E-graph, as
it represents several parse trees corresponding to all
the possible interpretations of the input string. The E-
graph contains a set of starting nodes, each of which
represents a parse tree root. Constraint enforcement is
performed by converting each implicit node into ev-
ery possible explicit node sequence that can be de-
rived from the implicit node and satisfies the speci-
fied constraints; that is, by expanding the each im-
plicit node.
Only the nodes that conform valid parse trees
are needed in the parse graph. In order to generate
only these nodes, each one of the implicit nodes in
the starting node set of the I-graph is recursively ex-
panded using memoization. Each possible resulting
explicit node is the root of a parse tree in the E-graph.
3.4.1 Algorithm Description
The expansion of an implicit node is performed by
finding every possible reduction of a sequence of ex-
plicit nodes that generates that node. Each one of
these reductions produces an explicit node. Whenever
an implicit node is found and needed in order to make
the reductions progress, it is expanded recursively. It
should be noted that this procedure is different from
parsing itself in that the actual bounds of the reduc-
tions for every node are known.
The expand procedure in Figure 12 expands an
implicit node by applying every possible production
that could generate it and produces a set of explicit
nodes. The use of the history set inhibits entering an
infinite loop when processing infinitely recursive pro-
duction sets, as it avoids the expansion of a node as
an indirect requirement of expanding the same node.
The apply procedure in Figure 13 applies a pro-
duction by matching the RHS symbol given by the
matched + 1 index of it with the n node, expanding
the nodes that follows it, and recursively applying the
next RHS symbols of the production.
The checkConstraints procedure is the responsible
for the enforcement of the constraints specified by the
developer.
3.4.2 Supported Constraints
Fence supports associativity constraints, selection
precedence constraints, composition precedence con-
straints, and custom-designed constraints.
The fact that the constraint check is per-
formed during the graph expansion improves the
Fence-AContext-freeGrammarParserwithConstraintsforModel-drivenLanguageSpecification
9