package gutenberg.pegdown.plugin; import org.parboiled.BaseParser; import org.parboiled.Rule; import org.parboiled.annotations.BuildParseTree; import org.parboiled.annotations.SuppressSubnodes; import org.parboiled.support.StringBuilderVar; import org.pegdown.Parser; /** * @author <a href="http://twitter.com/aloyer">@aloyer</a> */ @BuildParseTree public class AttributesParser extends Parser { public AttributesParser() { super(ALL, 1000l, DefaultParseRunnerProvider); } public Rule attributesRules() { return Sequence( Sp(), "{", push(new AttributeListNode()), CommaSeparatedAttributes(), "}", Sp(), FirstOf(Newline(), EOI) ); } public Rule CommaSeparatedAttributes() { return Sequence( Attribute(), ((AttributeListNode) peek(1)).append((AttributeNode) pop()), ZeroOrMore( Sequence( ",", Attribute(), ((AttributeListNode) peek(1)).append((AttributeNode) pop()) ) ) ); } @SuppressSubnodes public Rule Attribute() { return NodeSequence( Name(), "=", Value(), push(new AttributeNode((String) pop(1), (String) pop()))); } @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()) ); } @SuppressSubnodes public Rule Value() { StringBuilderVar text = new StringBuilderVar(); return Sequence(FirstOf( Sequence(Ch('"'), OneOrMore(TestNot('"'), BaseParser.ANY, text.append(matchedChar())), Ch('"')), OneOrMore(TestNot("}"), TestNot(","), TestNot(Newline()), BaseParser.ANY, text.append(matchedChar()))), push(text.getString()) ); } }