2010-11-22 142 views
2

我已经为一种类型的DSL编写了JJTree(JavaCC)配置,并成功标记了给定格式的文件,并在请求时转储AST。如何使用JavaCC/JJTree存储令牌?

问题是树中的每个节点都是空的,因为我当前没有存储令牌(我无法理解这些例子)。

这里是我的.jjt文件的一部分:

SimpleNode Start() #Root : {} { 
    (
    (Section1())? 
    (Section2())? 
    (Section3())* 
) { 
    return jjtThis; 
    } 
} 

void Section3() #Section3 : {} 
{ 
    <SECTION_3> Identifier() <LBRACE > 
    Header() 
     (Details() <SEMICOLON>)* 
    <RBRACE> 
} 

我想存储SECTION1,第2节和为Section3引用列表的引用根节点。我希望Section3节点存储标识符,标题块并保留详细信息块的列表。

我的fill .jjt文件是数百行,但我觉得如果我能理解这两个部分,那么我就能理解JJTree是如何工作的。请让我知道如何正确使用JJTree。

谢谢。

回答

2

如果您查看SimpleNode类,您会注意到它的实例会自动存储对其父节点和子节点的引用(除非它们的创建使用#void进行了抑制)。例如,您的根节点将包含对0..1 Section1节点,0..1 Section2节点和0 .. * Section3节点的引用,并且可以使用返回节点对象的jjtGetChild()方法访问它们。要确定此子节点是否为Section1,Section2或Section3节点,可以调用它的toString()方法(如dump()那样)。另外,如果您厌倦了这种初始节点迭代和toString检查的风格,您可以定义自己的节点类型,而不是依赖SimpleNode实现。在我下面的例子中,Start()现在返回一个自定义RootNode,而不是一个普通的SimpleNode。 RootNode包含对其子节点的特定引用(根据需要定义这些节点的getter)。请注意,我的简短片段假定Section1/2/3()都返回自定义节点,但这不是是这种情况......从您所说的话,你想要一个自定义节点为Section3(),但如果Section1/2是微不足道的,你可以将它们留作SimpleNodes。

RootNode Start() : 
{ 
    Section1Node s1Node = null; 
    Section2Node s2Node = null; 

    List s3Nodes = new LinkedList(); 
    Section3Node s3Node = null; 
} 
{ 
    (
    (s1Node = Section1())? 
    (s2Node = Section2())? 
    (s3Node = Section3() {s3Nodes.add(s3Node); })* 
) { 

    return new RootNode(s1Node, s2Node, s3Nodes); 
    } 
} 

如果你遍历你的解析树,并与您的节点做复杂的事情,它可能是一个好主意,它的一些移动到Visitor class让你与你的节点做的是从分离节点类本身。您最终可能会有几个访问类,每个访问类在分析树上执行一个函数,并且对每种类型的节点都有访问方法重载。

让我知道是否有什么你不明白。我不是JavaCC专家(我曾在uni使用它)但我应该能够帮助你:)

+0

感谢您的信息。如果可能的话,你可以告诉我如何处理这个例子而不定义自定义节点类(如何添加字段来将自定义标记保存在已有的JJTree定义的节点类型中)?那就是 - 举一个你在第一段中解释的方法的例子。 – Chris 2010-11-23 17:38:12