操纵AST以更改输入文本

时间:2013-01-04 12:59:40

标签: java antlr antlr3 abstract-syntax-tree

我有一个更普遍的问题。

我目前正在使用ANTLR v3.4开展项目 - 这是我们的想法:

  • 解析一些输入并在过程中将重要部分存储在Map中。
  • 在表单中显示已解析的输入(请参阅此Example Picture)。表单字段由键命名并填充Map的值,而文本输入字段包含整个输入。

因此,如果用户在底部输入/更改文本,则表单字段的内容也将更改,因为构建Map的解析器语法中的代码操作(用作填充表单字段的输入) )。

但我们还想要另一个方向:如果用户更改其中一个表单字段中的值,则这些更改应反映在底部的文本中。

我想过使用AST创建然后操作来完成这个任务。我已经在语法中添加了树重写规则。但我不太确定如何在Map,AST和如何创建输出之间建立连接。

我是否走在正确的轨道上?还有其他想法吗?

修改

所以我按照你的建议把假节点直接放到一个可以改变的数据结构中,一切都很好。

但现在我还有其他两个问题:

  1. 我如何添加令牌?输入中有可选部分,因此某些表单字段可能为空。如果我将表单字段更改为给定值,则必须在树中创建新节点。我该怎么做?我必须确定将新节点放在哪里......
  2. 我如何删除令牌?因此,如果我将某个表单字段的值更改为“空”,则必须删除关联的节点,但这可能会影响周围的节点(例如,在列表中,每个标记后都有逗号)。我真的不知道该怎么做。
  3. 这是我目前的语法:

    parser grammar TestASTParser;
    
    options {
      language = Java;
      tokenVocab = TestASTLexer;
      output = AST;
    }
    
    ...
    
    entry
    :
    lemma=phrase 
    
    (lgrammatt=grammatts)? (lsemantic=semantics)? (lsubsemantic=subsemantics)?
    
    SEP 
    
    translat=phrase  
    
    (tgrammatt=grammatts )? (tsemantic=semantics)? (tsubsemantic=subsemantics)?
    
    EOF
    
      -> ^(ENTRY 
             ^(LEMMA ^(LEMMA_TEXT $lemma) ^(LEMMA_GRAMM $lgrammatt)? 
             ^(LEMMA_SEM $lsemantic)? ^(LEMMA_SUBSEM $lsubsemantic)?) 
          ^(SEPARATOR SEP)
           ^(TRANSLATION 
              ^(TRANSLAT_TEXT $translat) ^(TRANSLAT_GRAMM $tgrammatt)? 
              ^(TRANSLAT_SEM $tsemantic)? ^(TRANSLAT_SUBSEM $tsubsemantic)?)
           )
    
    ;
    
    phrase
    :
        t=((options{ greedy = false; }:.)+)
    
        -> PHRASE[$phrase.text]
    ;
    
    grammatts
    :
      OPEN_BRACKET grammlist CLOSE_BRACKET
    ;
    
    semantics:
      LEFT_CURLY phrase RIGHT_CURLY
    ;
    
    subsemantics:
      D_LEFT_CURLY phrase D_RIGHT_CURLY
    ;
    
    grammlist
    :
       grammatt (COMMA grammatt)*
    ;
    
    grammatt:
        (GENUS | GRAMMATT)
    ; 
    

    因此测试输入的结果树

    Angeber(in) [f] {Großkotz} {{xyz}} <> baterlunza(a) [m(f), refl] {boeser buba}

    看起来像this(黄色节点总是在那里,其他一切都是可选的)。因此,如果我在表单字段中将“refl”更改为“”,则节点“refl”应该消失,但在它之前也应该是“,”。如果我删除LEMMA_GRAMM下面的“f”,则整个子树必须消失(因为列表不能为空)。或者,如果我想将子语义添加到TRANSLATION,我将不得不为花括号TRANSLAT_SUBSEM{{创建相应的节点}}以及子节点。

    我真的不知道从哪里开始。我的树结构对此有好处吗?我是否需要自己实施BaseTree?或者只是简单的Java?

1 个答案:

答案 0 :(得分:0)

我不知道这是否直接适合您的情况。但是在使用Xtext时,您还会获得相应的EMF Model。然后,您的用户界面基本上是视图上半部分的EMF模型的一个表单,以及一个Xtext编辑器,用于视图下半部分的EMF模型的to-text-serialized部分。由于视图的上部和下部都基于相同的EMF模型实例,因此视图的任一部分中的更改都可以反映在任何其他部分中。 Xtext将为您提供下层表单中文本的必要解析和序列化。

由于您使用的是ANTLR,因此您可以将ANTLR语法迁移到Xtext。然而,这不是自动实现的,但不应该是一项太困难的任务。