/** * Returns a new parser that parses the receiver one or more times, separated * by a {@code separator}. */ public Parser separatedBy(Parser separator) { return new SequenceParser(this, new SequenceParser(separator, this).star()) .map((List<List<List<Object>>> input) -> { List<Object> result = new ArrayList<>(); result.add(input.get(0)); input.get(1).forEach(result::addAll); return result; }); }
.seq(of(EQUALS)) .seq(ref("space optional")) .seq(ref("attributeValue")) .map((List<?> list) -> callback.createAttribute((TName) list.get(0), (String) list.get(4)))); def("attributeValue", ref("attributeValueDouble") .or(ref("attributeValueSingle")) def("attributeValueDouble", of(DOUBLE_QUOTE) .seq(new XmlCharacterParser(DOUBLE_QUOTE, 0)) .seq(of(DOUBLE_QUOTE))); def("attributeValueSingle", of(SINGLE_QUOTE) .seq(new XmlCharacterParser(SINGLE_QUOTE, 0)) .seq(of(SINGLE_QUOTE))); def("attributes", ref("space") .seq(ref("attribute")) .pick(1) .star()); def("comment", of(OPEN_COMMENT) .seq(any().starLazy(of(CLOSE_COMMENT)).flatten()) .seq(of(CLOSE_COMMENT)) .map((List<String> list) -> callback.createComment(list.get(1)))); def("cdata", of(OPEN_CDATA) .seq(any().starLazy(of(CLOSE_CDATA)).flatten()) .seq(of(CLOSE_CDATA)) .map((List<String> list) -> callback.createCDATA(list.get(1)))); def("content", ref("characterData") .or(ref("element")) def("doctype", of(OPEN_DOCTYPE)
void smalltalk() { def("array", token("{") .seq(ref("expression").separatedBy(ref("periodToken")) .seq(ref("periodToken").optional()).optional()) .seq(token("}"))); def("arrayItem", ref("literal") .or(ref("symbolLiteralArray")) def("arrayLiteral", token("#(") .seq(ref("arrayItem").star()) .seq(token(")"))); def("arrayLiteralArray", token("(") .seq(ref("arrayItem").star()) .seq(token(")"))); def("assignment", ref("variable") .seq(ref("assignmentToken"))); def("block", token("[") .seq(ref("blockBody")) .seq(token("]"))); def("blockArgument", token(":") .seq(ref("variable"))); def("byteLiteral", token("#[") .seq(ref("numberLiteral").star()) .seq(token("]"))); def("byteLiteralArray", token("[") .seq(ref("numberLiteral").star()) .seq(token("]"))); def("cascadeExpression", ref("keywordExpression")
.seq(of(']').trim())); def("elements", ref("value").separatedBy(of(',').trim())); def("members", ref("pair").separatedBy(of(',').trim())); def("object", of('{').trim() .seq(ref("members").optional()) .seq(of('}').trim())); def("pair", ref("stringToken") .seq(of(':').trim()) .seq(ref("value"))); def("value", ref("stringToken") .or(ref("numberToken")) def("numberPrimitive", of('-').optional() .seq(of('0').or(digit().plus())) .seq(of('.').seq(digit().plus()).optional()) .seq(anyOf("eE").seq(anyOf("-+").optional()) .seq(digit().plus()).optional())); def("stringPrimitive", of('"') .seq(ref("characterPrimitive").star()) .seq(of('"')));
/** * Returns a parser that consumes any input token (character), but the receiver. */ public Parser neg(String message) { return not(message).seq(CharacterParser.any()).pick(1); }
private void other() { // the original implementation uses a handwritten parser to // efficiently consume whitespace and comments def("whitespace", whitespace() .or(ref("comment"))); def("comment", of('"') .seq(any().starLazy(of('"'))) .seq(of('"'))); }
@Override public SequenceParser copy() { return new SequenceParser(Arrays.copyOf(parsers, parsers.length)); } }
/** * Returns a list of all successful overlapping parses of the {@code input}. */ @SuppressWarnings("unchecked") public <T> List<T> matches(String input) { List<Object> list = new ArrayList<>(); this.and().map(list::add).seq(any()).or(any()).star().parse(input); return (List<T>) list; }
/** * Returns a new parser that parses the receiver one or more times, separated * and possibly ended by a {@code separator}." */ public Parser delimitedBy(Parser separator) { return separatedBy(separator) .seq(separator.optional()) .map((List<List<Object>> input) -> { List<Object> result = new ArrayList<>(input.get(0)); if (input.get(1) != null) { result.add(input.get(1)); } return result; }); }
def("radixInteger", ref("radixSpecifier") .seq(of('r')) .seq(ref("radixDigits"))); def("radixSpecifier", ref("digits")); def("radixDigits", pattern("0-9A-Z").plus()); .seq(ref("exponentLetter") .seq(ref("exponent")) .optional())); def("mantissa", ref("digits") .seq(of('.')) .seq(ref("digits"))); def("exponent", of('-') .seq(ref("decimalInteger"))); .seq(ref("fractionalDigits").optional())); def("scaledMantissa", ref("decimalInteger") .or(ref("mantissa")));
/** * Returns a parser that consumes any input token (character), but the receiver. */ public Parser neg(String message) { return not(message).seq(CharacterParser.any()).pick(1); }
@Override public SequenceParser copy() { return new SequenceParser(Arrays.copyOf(parsers, parsers.length)); } }
/** * Returns a list of all successful overlapping parses of the {@code input}. */ @SuppressWarnings("unchecked") public <T> List<T> matches(String input) { List<Object> list = new ArrayList<>(); this.and().map(list::add).seq(any()).or(any()).star().parse(input); return (List<T>) list; }
/** * Returns a new parser that parses the receiver one or more times, separated * and possibly ended by a {@code separator}." */ public Parser delimitedBy(Parser separator) { return separatedBy(separator) .seq(separator.optional()) .map((List<List<Object>> input) -> { List<Object> result = new ArrayList<>(input.get(0)); if (input.get(1) != null) { result.add(input.get(1)); } return result; }); }
/** * Returns a new parser that parses the receiver one or more times, separated * by a {@code separator}. */ public Parser separatedBy(Parser separator) { return new SequenceParser(this, new SequenceParser(separator, this).star()) .map((List<List<List<Object>>> input) -> { List<Object> result = new ArrayList<>(); result.add(input.get(0)); input.get(1).forEach(result::addAll); return result; }); }
def("pattern", ref("pattern_element").plus()); def("pattern_element", ref("chars").or(ref("delimitedPlaceholder"))); def("delimitedPlaceholder", of("${").seq(ref("placeholder"), of('}')).pick(1)); def("placeholder", ref("inner_placeholder").or(ref("withPrefixPlaceholder"))); def("withPrefixPlaceholder", ref("prefix_placeholder").seq(ref("inner_placeholder"))); def("auto_prefix_placeholder", of('<')); def("meta", of("meta.").seq(ref("chars")).pick(1)); def("sys", of("sys.").seq(ref("chars")).pick(1)); def("env", of("env.").seq(ref("chars")).pick(1));
/** * Returns a parser that accepts the receiver followed by {@code others}. The resulting parser * returns a list of the parse result of the receiver followed by the parse result of {@code * others}. Calling this method on an existing sequence code not nest this sequence into a new one, * but instead augments the existing sequence with {@code others}. */ public SequenceParser seq(Parser... others) { Parser[] parsers = new Parser[1 + others.length]; parsers[0] = this; System.arraycopy(others, 0, parsers, 1, others.length); return new SequenceParser(parsers); }
/** * Returns a parser that accepts the receiver followed by {@code others}. The resulting parser * returns a list of the parse result of the receiver followed by the parse result of {@code * others}. Calling this method on an existing sequence code not nest this sequence into a new one, * but instead augments the existing sequence with {@code others}. */ public SequenceParser seq(Parser... others) { Parser[] parsers = new Parser[1 + others.length]; parsers[0] = this; System.arraycopy(others, 0, parsers, 1, others.length); return new SequenceParser(parsers); }
@Override public SequenceParser seq(Parser... others) { Parser[] array = Arrays.copyOf(parsers, parsers.length + others.length); System.arraycopy(others, 0, array, parsers.length, others.length); return new SequenceParser(array); }
@Override public SequenceParser seq(Parser... others) { Parser[] array = Arrays.copyOf(parsers, parsers.length + others.length); System.arraycopy(others, 0, array, parsers.length, others.length); return new SequenceParser(array); }