Fixed parser weirdness. More readable parser finished.

For whatever reason, writing the parser in Groovy was causing weird errors
to occur when the parser or parse runner was created. Using a plain Java
source file fixed this.
This commit is contained in:
Jonathan Bernard 2011-08-26 05:51:29 -05:00
parent e8ebcd4998
commit 13e0e72fed
4 changed files with 85 additions and 62 deletions

View File

@ -1,62 +0,0 @@
package com.jdblabs.jlp
import org.parboiled.BaseParser
import org.parboiled.Rule
import org.parboiled.annotations.*
public class JLPPegParser extends BaseParser<Object> {
public Rule CodePage() {
println "Parsing CodePage"
ZeroOrMore(FirstOf(
DocBlock(),
CodeBlock())) }
Rule DocBlock() {
OneOrMore(FirstOf(
DirectiveBlock(),
MarkdownBlock())) }
Rule CodeBlock() {
OneOrMore(Sequence(
TestNot(DOC_START), RemainingLine())) }
Rule DirectiveBlock() {
FirstOf(
// there is a bug in parboiled that prevents sequences of greater
// than 2, so this ia workaround
Sequence(
Sequence(
Sequence(DOC_START, DIRECTIVE_START),
Sequence(LongDirective(), RemainingLine())),
Sequence(Optional(MarkdownBlock()))),
Sequence(
Sequence(DOC_START, DIRECTIVE_START),
Sequence(LineDirective(), RemainingLine()))) }
Rule LongDirective() { FirstOf(AUTHOR_DIR, DOC_DIR, EXAMPLE_DIR) }
Rule LineDirective() { ORG_DIR }
Rule MarkdownBlock() { OneOrMore(MarkdownLine()) }
Rule MarkdownLine() {
Sequence(DOC_START, Sequence(TestNot(DIRECTIVE_START), RemainingLine())) }
Rule RemainingLine() { Sequence(OneOrMore(NOT_EOL), EOL) }
Rule DOC_START = String("%% ")
Rule EOL = Ch('\n' as char)
Rule NOT_EOL = Sequence(TestNot(EOL), ANY)
Rule DIRECTIVE_START= Ch('@' as char)
Rule SLASH = Ch('/' as char)
// directive terminals
Rule AUTHOR_DIR = IgnoreCase("author")
Rule DOC_DIR = IgnoreCase("doc")
Rule EXAMPLE_DIR = IgnoreCase("example")
Rule ORG_DIR = IgnoreCase("org")
}

View File

@ -0,0 +1,58 @@
package com.jdblabs.jlp;
import org.parboiled.Action;
import org.parboiled.BaseParser;
import org.parboiled.Context;
import org.parboiled.Rule;
import org.parboiled.annotations.*;
public class JLPPegParser extends BaseParser<Object> {
public Rule CodePage() {
return ZeroOrMore(FirstOf(
DocBlock(),
CodeBlock())); }
Rule DocBlock() {
return OneOrMore(FirstOf(
DirectiveBlock(),
MarkdownBlock())); }
Rule CodeBlock() {
return OneOrMore(Sequence(
TestNot(DOC_START), RemainingLine())); }
Rule DirectiveBlock() {
return FirstOf(
// there is a bug in parboiled that prevents sequences of greater
// than 2, so this ia workaround
Sequence(DOC_START, DIRECTIVE_START, LongDirective(),
RemainingLine(), Optional(MarkdownBlock())),
Sequence(DOC_START, DIRECTIVE_START, LineDirective(),
RemainingLine())); }
Rule LongDirective() { return FirstOf(AUTHOR_DIR, DOC_DIR, EXAMPLE_DIR); }
Rule LineDirective() { return ORG_DIR; }
Rule MarkdownBlock() { return OneOrMore(MarkdownLine()); }
Rule MarkdownLine() {
return Sequence(DOC_START, TestNot(DIRECTIVE_START), RemainingLine()); }
Rule RemainingLine() { return Sequence(OneOrMore(NOT_EOL), EOL); }
Rule DOC_START = String("%% ");
Rule EOL = Ch('\n');
Rule NOT_EOL = Sequence(TestNot(EOL), ANY);
Rule DIRECTIVE_START= Ch('@');
Rule SLASH = Ch('/');
// directive terminals
Rule AUTHOR_DIR = IgnoreCase("author");
Rule DOC_DIR = IgnoreCase("doc");
Rule EXAMPLE_DIR = IgnoreCase("example");
Rule ORG_DIR = IgnoreCase("org");
}

BIN
src/test/TestParser.class Normal file

Binary file not shown.

27
src/test/TestParser.java Normal file
View File

@ -0,0 +1,27 @@
import org.parboiled.BaseParser;
import org.parboiled.Parboiled;
import org.parboiled.Rule;
import org.parboiled.annotations.BuildParseTree;
import org.parboiled.parserunners.ReportingParseRunner;
import org.parboiled.support.ParsingResult;
import static org.parboiled.support.ParseTreeUtils.printNodeTree;
@BuildParseTree
public class TestParser extends BaseParser<Object> {
public Rule S() {
return OneOrMore(
Sequence(A(), OneOrMore(B()), C())); }
Rule A() { return Ch('a'); }
Rule B() { return Ch('b'); }
Rule C() { return Ch('c'); }
public static void main(String[] args) {
TestParser parser = Parboiled.createParser(TestParser.class);
ReportingParseRunner parseRunner = new ReportingParseRunner(parser.S());
ParsingResult result = parseRunner.run("abbbbcabc");
System.out.println(result.matched ? printNodeTree(result) + "\n" : "No Match");
}
}