2014-09-01 35 views
1

我正在使用this ANTLR 3 grammar和ANTLRWorks来测试该语法。ANTRL 3语法省略了部分输入源代码

但我不明白为什么我的输入文本的某些部分被省略。

我想重写这个语法并在AST/CST中显示源文件(输入)的每个元素(lparen,keywords,分号,..)。

我试过了一切,但没有成功。有经验的人可以帮助我吗?

enter image description here

分析树:

parse tree

+3

首先,如果你想显示每个标记,你将不得不显示分析树,而不是AST,根据定义它将缺少这个信息。那么,为什么不尝试ANTLR v4 [ECMAScript语法](https://github.com/antlr/grammars-v4/tree/master/ecmascript)呢? – 2014-09-01 22:31:02

+0

谢谢你的回复,但问题是因为我必须使用ANTLR v3来完成这个项目,而且我需要创建具体的语法树(CST),所以Parse Tree对我没有多大帮助。我需要在AST中包含所有源元素(lparen,关键字,点等)。 – 2014-09-01 22:37:01

+2

在我的理解中,* CST *只是* parse tree *的同义词。我不知道你在做什么,但在我看来,你需要在这个抽象层次上工作,而不是在* AST *层面。 – 2014-09-02 07:25:22

回答

1

我已经成功地缩小它的semic规则:

/* 
This rule handles semicolons reported by the lexer and situations where the ECMA 3 specification states there should be semicolons automaticly inserted. 
The auto semicolons are not actually inserted but this rule behaves as if they were. 

In the following situations an ECMA 3 parser should auto insert absent but grammaticly required semicolons: 
- the current token is a right brace 
- the current token is the end of file (EOF) token 
- there is at least one end of line (EOL) token between the current token and the previous token. 

The RBRACE is handled by matching it but not consuming it. 
The EOF needs no further handling because it is not consumed by default. 
The EOL situation is handled by promoting the EOL or MultiLineComment with an EOL present from off channel to on channel 
and thus making it parseable instead of handling it as white space. This promoting is done in the action promoteEOL. 
*/ 
semic 
@init 
{ 
    // Mark current position so we can unconsume a RBRACE. 
    int marker = input.mark(); 
    // Promote EOL if appropriate 
    promoteEOL(retval); 
} 
    : SEMIC 
    | EOF 
    | RBRACE { input.rewind(marker); } 
    | EOL | MultiLineComment // (with EOL in it) 
    ; 

因此,EVIL分号插入罢工再次!

我不太确定,但我认为这些mark/rewind调用不同步。在为分支选择输入规则以进行实际匹配时,将执行@init块。它实际上创造了很多标记,但没有清除它们。但我不知道为什么它会像这样弄乱解析树。

总之,这里的同一个规则的工作版本:

semic 
@init 
{ 
    // Promote EOL if appropriate 
    promoteEOL(retval); 
} 
    : SEMIC 
    | EOF 
    | { int pos = input.index(); } RBRACE { input.seek(pos); } 
    | EOL | MultiLineComment // (with EOL in it) 
    ; 

这是更简单,不使用mark/rewind机制。

但有一个问题:分析树中的semic规则在结束大括号之前插入分号时会有一个子节点}。尝试在i--后删除分号并查看结果。您必须检测并在您的代码中处理它。 semic应该包含一个;标记,或包含EOL(这意味着在此处静默插入分号)。

+0

我很高兴我们在ANTLR 4中摆脱了“倒带”。 – 2014-09-04 01:06:48