2013-05-01 18 views
1

让我们假设我有一个简单的JavaCC语法解析加法和减法:的JavaCC:我怎样才能维持原来的文本(包括空格)


.... 
void CompilationUnit() : 
{} 
{ 
    (Expression())+ 
    EOF 
} 
void Expression() : 
{} 
{ 
    Number() 
    (
    Addition() 
    | Subtraction() 
)* 
} 
void Number() : 
{} 
{ 
    
} 
void Addition() : 
{} 
{ 
    Number() 
} 
void Subtraction() : 
{} 
{ 
    Number() 
} 

我有使用该语法产生的AST类以计算结果:


public class Calculator extends DepthFirstVisitor { 
    int result = -1; 
    public void visit(Expression n) { 
    if (result >= 0) System.out.println(toText(n) + " = " + result); 
    result = 0; 
    super.visit(n); 
    } 
    public void visit(Number n) { 
    ... 
    } 
    public void visit(Addition n) { 
    ... 
    } 
    .... 
} 

我能够计算表达式的值,但我也需要原始表达式(因为它出现了)。所以以下输入:

 
    5 + 2 - 1 
    2 + 1 

我想有以下输出:

 
5 + 2 - 1 = 6 
2 + 1 = 3 

不幸的是,因为我喜欢跳过空格或换行符角色,这是我得到的是:

 
5+2-1 = 6 
2+1 = 3 

有没有什么方法可以输出原始文本(包括跳过的字符)?

请注意实际问题要大得多,语法要复杂得多。所以我没有真正寻找特定于上述问题的解决方案(例如,预处理行并将它们拆分为换行符或修改方法以在每个令牌后面“手动”添加空格),但更像是使用某些JavaCC功能的解决方案。

回答

2

ANTLr和Xtext都支持空白和注释的“隐藏标记”。请参阅here以获得一些提示,或者使用Google。也许JavaCC有一些相似的概念。

编辑:JavaCC似乎使用术语“特殊令牌”。见here for some details

+0

是的JavaCC有特殊的标记。请参阅http://www.engr.mun.ca/~theo/JavaCC-FAQ/常见问题中的Q 5.2。 – 2013-05-01 23:22:23

0

基本上你不能在编译器中做到这一点。您必须在语法中将空格作为标记捕获,并允许它在任何地方被允许使用,而且这种语法无处不在,而且所产生的语法会非常复杂以至于无法执行或甚至无法生成。你必须做的是捕获对实体来自的源代码(行和列)中的坐标的引用:例如可能是当前行和列号的文本。

编译器的行为方式是有原因的。

+0

JavaCC(以及许多其他解析器生成器)使得这种操作非常容易,不会增加复杂性,从而破坏了您的答案。 – 2013-05-01 23:25:33