org.codehaus.jparsec
Class Parser.Reference<T>

java.lang.Object
  extended by java.util.concurrent.atomic.AtomicReference<Parser<T>>
      extended by org.codehaus.jparsec.Parser.Reference<T>
All Implemented Interfaces:
Serializable
Enclosing class:
Parser<T>

public static final class Parser.Reference<T>
extends AtomicReference<Parser<T>>

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 Map<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.codehaus.jparsec.Parser>) 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,
       new Map4<...>() {
         public Unary<Expr> map(unused, consequence, unused, alternative) {
           // (condition) -> Ternary(condition, consequence, alternative)
           return new Unary<Expr>() {
             ...
             return new TernaryExpr(condition, consequence, alternative);
           }
         }
       }));
   }
 

See Also:
Serialized Form

Constructor Summary
Parser.Reference()
           
 
Method Summary
 Parser<T> lazy()
          A Parser that delegates to the parser object referenced by this during parsing time.
 
Methods inherited from class java.util.concurrent.atomic.AtomicReference
compareAndSet, get, getAndSet, lazySet, set, toString, weakCompareAndSet
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Constructor Detail

Parser.Reference

public Parser.Reference()
Method Detail

lazy

public Parser<T> lazy()
A Parser that delegates to the parser object referenced by this during parsing time.



Copyright © 2014. All rights reserved.