JavaCC:如何维护原始文本(带空格)

时间:2013-05-01 10:24:06

标签: java 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 个答案:

答案 0 :(得分:2)

ANTLr和Xtext支持"隐藏的令牌"对于空白和评论。有关提示,请参阅here或使用该术语使用Google。也许JavaCC有一些类似的概念。

编辑:JavaCC似乎使用术语"特殊标记"。请参阅here for some details

答案 1 :(得分:0)

基本上你不能在编译器中这样做。你必须将空格捕获为语法中的一个标记,并允许它在任何地方被允许,这是无处不在的,并且结果语法将是如此复杂,以至于无法实现或甚至生成。您将需要捕获对实体来源的源代码(行和列)中的坐标的引用:例如,当前行和列号的文本。

编译器的行为与他们的行为方式有关。