Package org.jparsec

Class Parser.Reference<T>

  • All Implemented Interfaces:
    java.io.Serializable
    Enclosing class:
    Parser<T>

    public static final class Parser.Reference<T>
    extends java.util.concurrent.atomic.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 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:
    Serialized Form
    • Field Summary

      Fields 
      Modifier and Type Field Description
      private Parser<T> lazy  
    • Constructor Summary

      Constructors 
      Constructor Description
      Reference()  
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      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

        accumulateAndGet, compareAndExchange, compareAndExchangeAcquire, compareAndExchangeRelease, compareAndSet, get, getAcquire, getAndAccumulate, getAndSet, getAndUpdate, getOpaque, getPlain, lazySet, set, setOpaque, setPlain, setRelease, toString, updateAndGet, weakCompareAndSet, weakCompareAndSetAcquire, weakCompareAndSetPlain, weakCompareAndSetRelease, weakCompareAndSetVolatile
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
    • Field Detail

      • lazy

        private final Parser<T> lazy
    • Constructor Detail

      • Reference

        public Reference()
    • Method Detail

      • lazy

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