antlr4木偶式声明语法问题

时间:2013-02-02 15:04:04

标签: antlr4

我正在尝试为一个木偶风格的声明性语言编写一个语法。我有我的基本语法和JUnit测试,试图实现一个Listener方法来加载它。 JUnit测试捕获第一个资源但不捕获第二个资源,它几乎像resources规则永远不会被评估。我将记录语句添加到我的Loader中,资源永远不会被输入/退出。

    grammar Bosse;
    resources : resource+;
    resource : ID LBRACE STRING COLON attributes RBRACE ;
    attributes : keyvalue ( COMMA keyvalue )* COMMA? ;
    keyvalue : ID ASSIGN expr ;
    expr    : STRING
            | INT
            | FLOAT
            ;

    ID      : [a-z]+ ;

    STRING  : SQUOTE (SQESC|.)*? SQUOTE;

    SQESC   : '\\\'' | '\\\\' ;

    INT : DIGIT+ ;

    FLOAT   : DIGIT+ '.' DIGIT*
    | '.' DIGIT+
    ;

    ASSIGN : '=>' ;
    LBRACE : '{' ;
    RBRACE : '}' ;

    fragment
    SQUOTE : '\'' ;

    COLON  : ':' ;
    COMMA  : ',' ;

    WS     : (' '|'\n'|'\t'|'\r')+ -> skip ;

    fragment
    DIGIT  : [0-9] ;

我的BaseListener实现:

    public class BosseLoader extends BosseBaseListener {
            private List<Resource> resources = new ArrayList<Resource>();
    private String resourceType;
    private String resourceTitle;
    private Map<String,Object> attributes = new HashMap<String,Object>();

    private String parseString(String str) {
        str = str.substring(1, str.length()-1);
        str.replaceAll("\\\\(.)", "\1");
        return str;
    }

    public List<Resource> getResources() {
        return resources;
    }

    @Override
    public void enterResources(ResourcesContext ctx) {
        log.finest("entered "+ctx);
    }

    @Override
    public void exitResources(ResourcesContext ctx) {
        log.finest("entered "+ctx);
    }

    @Override
    public void enterResource(ResourceContext ctx) {
        log.finest("entered "+ctx);
        resourceType = ctx.ID().getText();
        resourceTitle = parseString(ctx.STRING().getText());
    }

    @Override
    public void exitResource(ResourceContext ctx) {
        log.finest("entered "+ctx);

        Resource r = new Resource() {
            public String getTitle() {
                return resourceTitle;
            }

            public String toString() {
                String type = resourceType.substring(0,1).toUpperCase()+resourceType.substring(1);
                return type+"["+resourceTitle+"]";
            }
        };
        resources.add(r);
        System.out.println(r);
        super.exitResource(ctx);
    }

    @Override
    public void enterAttributes(AttributesContext ctx) {
        log.finest("entered "+ctx);
        attributes = new HashMap<String,Object>();
    }

    @Override
    public void exitKeyvalue(KeyvalueContext ctx) {
        log.finest("entered "+ctx);
        attributes.put(ctx.ID().getText(),ctx.expr().getText());
    }
}

我的JUnit测试

    @Test
public void testSyntaxDouble() {
    System.out.println("testSyntaxDouble()");
    String data = "user { 'ruckc' : ensure => 'present' }\n"+
                  "user { 'cruck' : ensure => 'present' }\n";

    BosseLoader loader = new BosseLoader();

    BosseLexer lexer = new BosseLexer(new ANTLRInputStream(data));
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    BosseParser parser = new BosseParser(tokens);
    ParseTree tree = parser.resource();
    ParseTreeWalker walker = new ParseTreeWalker();
    walker.walk(loader, tree);

    assertEquals(2,loader.getResources().size());
    Resource r = loader.getResources().get(0);
    assertEquals("ruckc", r.getTitle());
    assertEquals("User[ruckc]", r.toString());
    r = loader.getResources().get(1);
    assertEquals("cruck", r.getTitle());
    assertEquals("User[cruck]", r.toString());
}

我的测试结果:

testSyntaxDouble()
FINEST: AM org.cruck.bosse.language.BosseLoader enterResource  entered []
FINEST: AM org.cruck.bosse.language.BosseLoader enterAttributes  entered [19]
FINEST: AM org.cruck.bosse.language.BosseLoader exitKeyvalue  entered [22 19]
FINEST: AM org.cruck.bosse.language.BosseLoader exitResource  entered []
User[ruckc]
Failed tests: 
  testSyntaxDouble(org.cruck.bosse.language.BosseLanguageTest): expected:<2> but was:<1>

0 个答案:

没有答案