예제 #1
0
 private static <T> Parser<Character, T> tok(Parser<Character, T> p) {
   return p.bind(x -> wspaces.then(retn(x)));
 }
예제 #2
0
/**
 * A grammar for JSON. Copied and adapted from
 * https://github.com/jon-hanson/parsecj/blob/master/src/test/java/org/javafp/parsecj/json/Grammar.java
 */
class Grammar {
  private static <T> Parser<Character, T> tok(Parser<Character, T> p) {
    return p.bind(x -> wspaces.then(retn(x)));
  }

  private static final Parser.Ref<Character, JValue> jvalue = Parser.ref();

  private static final Parser<Character, JValue> jnull =
      tok(string("null")).then(retn(jNull().asJValue())).label("null");

  private static final Parser<Character, Boolean> jtrue =
      tok(string("true").then(retn(Boolean.TRUE)));
  private static final Parser<Character, Boolean> jfalse =
      tok(string("false").then(retn(Boolean.FALSE)));

  private static final Parser<Character, JValue> jbool =
      tok(jtrue.or(jfalse).bind(b -> retn(jBoolean(b).asJValue()))).label("boolean");

  private static final Parser<Character, BigDecimal> bigdecimal =
      bind(regex("-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?"), s -> retn(new BigDecimal(s)))
          .label("bigdecimal");

  private static final Parser<Character, JValue> jnumber =
      tok(bigdecimal.bind(d -> retn(jNumber(d).asJValue()))).label("number");

  private static final Parser<Character, Byte> hexDigit =
      satisfy((Character c) -> Character.digit(c, 16) != -1)
          .bind(c -> retn((byte) Character.digit(c, 16)))
          .label("hex digit");

  private static final Parser<Character, Character> uni =
      hexDigit
          .bind(
              d0 ->
                  hexDigit.bind(
                      d1 ->
                          hexDigit.bind(
                              d2 ->
                                  hexDigit.bind(
                                      d3 -> retn((d0 << 0x3) & (d1 << 0x2) & (d2 << 0x1) & d0)))))
          .bind(i -> retn((char) i.intValue()));

  private static final Parser<Character, Character> esc =
      choice(
              chr('"'),
              chr('\\'),
              chr('/'),
              chr('b').then(retn('\b')),
              chr('f').then(retn('\f')),
              chr('n').then(retn('\n')),
              chr('r').then(retn('\r')),
              chr('t').then(retn('\t')),
              chr('u').then(uni))
          .label("escape character");

  private static final Parser<Character, Character> stringChar =
      (chr('\\').then(esc)).or(satisfy(c -> c != '"' && c != '\\'));

  private static final Parser<Character, String> jstring =
      tok(between(chr('"'), chr('"'), many(stringChar).bind(l -> retn(IList.listToString(l)))))
          .label("string");

  private static final Parser<Character, JValue> jtext =
      jstring.bind(s -> retn(jString(s).asJValue())).label("text");

  private static final Parser<Character, JValue> jarray =
      between(tok(chr('[')), tok(chr(']')), sepBy(jvalue, tok(chr(','))))
          .bind(l -> retn(jArray(IList.toList(l)).asJValue()))
          .label("array");

  private static final Parser<Character, Tuple2<String, JValue>> jfield =
      jstring.bind(name -> tok(chr(':')).then(jvalue).bind(value -> retn(tuple(name, value))));

  private static final Parser<Character, JValue> jobject =
      between(
              tok(chr('{')),
              tok(chr('}')),
              sepBy(jfield, tok(chr(','))).bind(lf -> retn(jObject(lf).asJValue())))
          .label("object");

  static {
    jvalue.set(choice(jnull, jbool, jnumber, jtext, jarray, jobject).label("JSON value"));
  }

  private static final Parser<Character, JValue> parser = wspaces.then(jvalue);

  static Reply<Character, JValue> parse(String str) {
    return parser.parse(State.of(str));
  }
}