Package org.jparsec
Class Parser.Reference<T>
- All Implemented Interfaces:
Serializable
An atomic mutable reference to
Parser
used in recursive grammars.
For example, the following is a recursive grammar for a simple calculator:
Terminals terms = Terminals.operators("(", ")", "+", "-");
Parser.Reference<Integer> ref = Parser.newReference();
Parser<Integer> literal = Terminals.IntegerLiteral.PARSER.map(new Function<String, Integer>() {
...
return Integer.parseInt(s);
});
Parser.Reference<Integer> parenthesized = // recursion in rule E = (E)
Parsers.between(terms.token("("), ref.lazy(), terms.token(")"));
ref.set(new OperatorTable()
.infixl(terms.token("+").retn(plus), 10)
.infixl(terms.token("-").retn(minus), 10)
.build(literal.or(parenthesized)));
return ref.get();
Note that a left recursive grammar will result in StackOverflowError
.
Use appropriate parser built-in parser combinators to avoid left-recursion.
For instance, many left recursive grammar rules can be thought as logically equivalent to
postfix operator rules. In such case, either OperatorTable
or Parser.postfix(org.jparsec.Parser<? extends java.util.function.Function<? super T, ? extends T>>)
can be used to work around left recursion.
The following is a left recursive parser for array types in the form of "T[]" or "T[][]":
Terminals terms = Terminals.operators("[", "]");
Parser.Reference<Type> ref = Parser.newReference();
ref.set(Parsers.or(leafTypeParser,
Parsers.sequence(ref.lazy(), terms.phrase("[", "]"), new Unary<Type>() {...})));
return ref.get();
And it will fail. A correct implementation is:
Terminals terms = Terminals.operators("[", "]");
return leafTypeParer.postfix(terms.phrase("[", "]").retn(new Unary<Type>() {...}));
A not-so-obvious example, is to parse the expr ? a : b
ternary operator. It too is a
left recursive grammar. And un-intuitively it can also be thought as a postfix operator.
Basically, we can parse "? a : b" as a whole into a unary operator that accepts the condition
expression as input and outputs the full ternary expression:
Parser<Expr> ternary(Parser<Expr> expr) {
return expr.postfix(
Parsers.sequence(
terms.token("?"), expr, terms.token(":"), expr,
(unused, then, unused, orelse) -> cond ->
new TernaryExpr(cond, then, orelse)));
}
- See Also:
-
Field Summary
Fields -
Constructor Summary
Constructors -
Method Summary
Methods inherited from class java.util.concurrent.atomic.AtomicReference
accumulateAndGet, compareAndExchange, compareAndExchangeAcquire, compareAndExchangeRelease, compareAndSet, get, getAcquire, getAndAccumulate, getAndSet, getAndUpdate, getOpaque, getPlain, lazySet, set, setOpaque, setPlain, setRelease, toString, updateAndGet, weakCompareAndSet, weakCompareAndSetAcquire, weakCompareAndSetPlain, weakCompareAndSetRelease, weakCompareAndSetVolatile
-
Field Details
-
lazy
-
-
Constructor Details
-
Reference
public Reference()
-
-
Method Details
-
lazy
AParser
that delegates to the parser object referenced bythis
during parsing time.
-