Class Parsers.Suffix

java.lang.Object
com.google.common.labs.parse.Parsers.Suffix
Direct Known Subclasses:
Suffix
Enclosing class:
Parsers

public static class Parsers.Suffix extends Object
Provides helpers to left-factor common prefixes followed by one or multiple optional suffixes.

Usually when you have an optional suffix, you should use optionallyFollowedBy() directly, such as:


 expr.optionallyFollowedBy("!", (Integer n) -> factorial(n));
 
However when there are more than one optional suffixes to be applied after the same prefix, it becomes harder to compose them without backtracking. You could use anyOf() like:

 Parser.anyOf(
     expr.followedBy("!").map(n -> factorial(n)),
     sequence(expr, exponential, (Expr i, Expr e) -> pow(i, e)));
 
But if performance is critical, the same expr rule will be re-evaluated during backtracking from choice #1 to choice #2, which is wasteful.

The following is an example that avoids backtracking, by using the Suffix helper and anyOf() to compose the optional suffix operators together before passing to optionallyFollowedBy():


 import static com.google.common.labs.parse.Parsers.Suffix.suffix;
 import com.google.common.labs.parse.Parsers.Suffix;

 expr.optionallyFollowedBy(
     anyOf(
         suffix("!", (Expr n) -> factorial(n)),
         suffix(exponential, (Expr i, Expr e) -> pow(i, e))),
     Suffix::apply);
 

Occasionally you may need to wrap the left parser's result with or without optional suffixes, regardless. For example, the parsed string needs to be wrapped in either one of Expr AST types as determined by the optional suffixes, or wrapped in the default LiteralExpr when no suffix is present, you can use:


 import static com.google.common.labs.parse.Parsers.Suffix.suffix;
 import com.google.common.labs.parse.Parsers.Suffix;

 Parser.sequence(
     expr,
     anyOf(
             suffix("!", FactorialExpr::new),
             suffix(exponential, PowExpr::new))
         .orElse(LiteralExpr::new),
     Suffix::apply);
 
Or even a single optional suffix can benefit too:

 import static com.google.common.labs.parse.Parsers.Suffix.suffix;
 import com.google.common.labs.parse.Parsers.Suffix;

 Parser.sequence(
     expr,
     suffix(exponential, PowExpr::new).orElse(LiteralExpr::new),
     Suffix::apply);
 
Since:
10.8
  • Method Summary

    Modifier and Type
    Method
    Description
    static <T,R> R
    apply(T prefix, Function<? super T, ? extends R> suffix)
    A convenience method to apply a suffix to a prefix.
    static <T,S,R> Parser<Function<T,R>>
    suffix(Parser<S> suffix, BiFunction<? super T, ? super S, ? extends R> combiner)
    A suffix parser that combines together with its prefix parse's result using the combiner function.
    static <T,R> Parser<Function<T,R>>
    suffix(String suffix, Function<? super T, ? extends R> mapper)
    A suffix parser that uses the mapper function to transform the prefix's result.
    static <T> Parser<T>
    withPrefixes(Parser<? extends Function<? super T, ? extends T>> prefix, Parser<? extends T> suffix)
    Returns a parser that matches the prefix parser zero or more times before suffix and applies the result functions iteratively, in First-In, Last-Out order.
    static <T> Parser<T>
    withPrefixes(String prefix, Parser<? extends T> suffix, UnaryOperator<T> prefixFunction)
    Returns a parser that matches zero or more occurrences of the prefix string before suffix and applies the prefixFunction iteratively for each matched prefix.

    Methods inherited from class java.lang.Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Method Details

    • withPrefixes

      public static <T> Parser<T> withPrefixes(String prefix, Parser<? extends T> suffix, UnaryOperator<T> prefixFunction)
      Returns a parser that matches zero or more occurrences of the prefix string before suffix and applies the prefixFunction iteratively for each matched prefix.

      For example:

      
       import static com.google.common.labs.parse.Parsers.UNSIGNED_INTEGER;
       import static com.google.common.labs.parse.Parsers.Suffix.withPrefixes;
      
       Parser<Integer> number = withPrefixes("-", UNSIGNED_INTEGER.map(Integer::parseInt), n -> -n);
       
    • withPrefixes

      public static <T> Parser<T> withPrefixes(Parser<? extends Function<? super T, ? extends T>> prefix, Parser<? extends T> suffix)
      Returns a parser that matches the prefix parser zero or more times before suffix and applies the result functions iteratively, in First-In, Last-Out order.

      For example:

      
       Parser<Declaration> declaration =
           withPrefixes(modifier.map(m -> id -> id.withModifier(m)), IDENTIFIER);
       
    • suffix

      public static <T,S,R> Parser<Function<T,R>> suffix(Parser<S> suffix, BiFunction<? super T, ? super S, ? extends R> combiner)
      A suffix parser that combines together with its prefix parse's result using the combiner function.
    • suffix

      public static <T,R> Parser<Function<T,R>> suffix(String suffix, Function<? super T, ? extends R> mapper)
      A suffix parser that uses the mapper function to transform the prefix's result.
    • apply

      public static <T,R> R apply(T prefix, Function<? super T, ? extends R> suffix)
      A convenience method to apply a suffix to a prefix. When passed to the optionallyFollowedBy() as a method reference (Suffix::apply), it reads in the intuitive encounter order.