public Rule Verbatim() { StringBuilderVar text = new StringBuilderVar(); StringBuilderVar line = new StringBuilderVar(); return NodeSequence( OneOrMore( ZeroOrMore(BlankLine(), line.append('\n')), Indent(), push(currentIndex()), OneOrMore( FirstOf( Sequence('\t', line.append(repeat(' ', 4-(currentIndex()-1-(Integer)peek())%4))), Sequence(NotNewline(), ANY, line.append(matchedChar())) ) ), Newline(), text.appended(line.getString()).append('\n') && line.clearContents() && drop() ), push(new VerbatimNode(text.getString())) ); }
public RootNode parseInternal(StringBuilderVar block) { char[] chars = block.getChars(); int[] ixMap = new int[chars.length + 1]; // map of cleaned indices to original indices // strip out CROSSED_OUT characters and build index map StringBuilder clean = new StringBuilder(); for (int i = 0; i < chars.length; i++) { char c = chars[i]; if (c != CROSSED_OUT) { ixMap[clean.length()] = i; clean.append(c); } } ixMap[clean.length()] = chars.length; // run inner parse char[] cleaned = new char[clean.length()]; clean.getChars(0, cleaned.length, cleaned, 0); RootNode rootNode = parseInternal(cleaned); // correct AST indices with index map fixIndices(rootNode, ixMap); return rootNode; }
@Cached public Rule LinkSource() { StringBuilderVar url = new StringBuilderVar(); return FirstOf( Sequence('(', LinkSource(), ')'), Sequence('<', LinkSource(), '>'), Sequence( OneOrMore( FirstOf( Sequence('\\', AnyOf("()"), url.append(matchedChar())), Sequence(TestNot(AnyOf("()>")), Nonspacechar(), url.append(matchedChar())) ) ), push(url.getString()) ), push("") ); }
boolean appendCrossed(StringBuilderVar block) { int iMax = matchLength(); for (int i = 0; i < iMax; i++) { block.append(CROSSED_OUT); } return true; }
@SuppressSubnodes Rule CaptureLineIgnored() { StringBuilderVar text = new StringBuilderVar(); return Sequence( ZeroOrMore(TestNot(Newline()), BaseParser.ANY), ((IgnoredLineAware) peek()).appendIgnoredLine(text.getString())); }
public Rule Box() { StringBuilderVar inner = new StringBuilderVar(); return NodeSequence( OneOrMore( xcrossedOut(Sequence('G', '>', Optional(' ')), inner), Line(inner) ), // trigger a recursive parsing run on the inner source we just built // and attach the root of the inner parses AST push(new GenericBoxNode( xwithIndicesShifted( delegate.get().parseInternal(inner), (Integer) peek() ).getChildren())) ); }
/** * Appends the given string. * If this instance is currently uninitialized the given string is used for initialization. * * @param text the text to append * @return true */ public boolean append(String text) { if (get() == null) return set(new StringBuilder(text)); get().append(text); return true; }
Node parseListBlock(StringBuilderVar block) { Context<Object> context = getContext(); Node innerRoot = parseInternal(block); setContext(context); // we need to save and restore the context since we might be recursing block.clearContents(); //debugMsg("parsed list block " + innerRoot.toString() + " adjusting indices by " + getContext().getValueStack().peek(), block.getString()); return withIndicesShifted(innerRoot, (Integer) context.getValueStack().pop()); }
public Rule FootnoteContent() { StringBuilderVar ref = new StringBuilderVar(); StringBuilderVar txt = new StringBuilderVar(); return NodeSequence( '[', OneOrMore(TestNot(']'), ANY, ref.append(matchedChar())), ']', ':', Sp(), ZeroOrMore(TestNot(BlankLine()), ANY, txt.append(matchedChar())), FirstOf(BlankLine(), EOI), push(new LinkContentNode(ref.getString(), txt.getString()))); }
boolean appendCrossedLessOne(StringBuilderVar block) { int iMax = matchLength() - 1; for (int i = 0; i < iMax; i++) { block.append(CROSSED_OUT); } return true; }
public Rule FencedCodeBlock() { StringBuilderVar text = new StringBuilderVar(); Var<Integer> markerLength = new Var<Integer>(); return NodeSequence( CodeFence(markerLength), TestNot(CodeFence(markerLength)), // prevent empty matches ZeroOrMore(BlankLine(), text.append('\n')), OneOrMore(TestNot(Newline(), CodeFence(markerLength)), ANY, text.append(matchedChar())), Newline(), push(new VerbatimNode(text.appended('\n').getString(), popAsString())), CodeFence(markerLength), drop() ); }
Rule legend() { StringBuilderVar text = new StringBuilderVar(); return Sequence(Sp(), "legend", Sp(), ":", OneOrMore(TestNot(Newline()), BaseParser.ANY, text.append(matchedChar())), Newline(), ((ChartNode) peek()).displayLegend(text.getString())); }
public Rule Line(StringBuilderVar sb) { return Sequence( Sequence(ZeroOrMore(NotNewline(), ANY), Newline()), sb.append(match()) ); }
public Rule BlockQuote() { StringBuilderVar inner = new StringBuilderVar(); StringBuilderVar optional = new StringBuilderVar(); return NodeSequence( OneOrMore( CrossedOut(Sequence('>', Optional(' ')), inner), Line(inner), ZeroOrMore( TestNot('>'), TestNot(BlankLine()), Line(inner) ), // ZeroOrMore(BlankLine()), inner.append(match()) Optional(Sequence(OneOrMore(BlankLine()), optional.append(match()), Test('>')), inner.append(optional.getString()) && optional.clearContents()) ), // vsch: the block quotes won't parse into Para because they will not be followed by a blank line, // unless the last line of the block quote is an empty block-quote line: ">". We append one here to // take care of that possibility, now that we don't include blank lines after a block quote we add one extra inner.append("\n\n"), // trigger a recursive parsing run on the inner source we just built // and attach the root of the inner parses AST push(new BlockQuoteNode(withIndicesShifted(parseInternal(inner), (Integer) peek()).getChildren())) ); }
@SuppressSubnodes public Rule Name() { StringBuilderVar text = new StringBuilderVar(); return Sequence(FirstOf( Sequence(Ch('"'), OneOrMore(TestNot('"'), BaseParser.ANY, text.append(matchedChar())), Ch('"')), OneOrMore(TestNot("="), TestNot(Newline()), BaseParser.ANY, text.append(matchedChar()))), push(text.getString()) ); }
/** * Appends the given string. * If this instance is currently uninitialized the given string is used for initialization. * * @param text the text to append * @return this instance */ public StringBuilderVar appended(String text) { append(text); return this; }