我有一个更一般的问题。
我目前正在使用 ANTLR v3.4 开发一个项目 - 这是我们的想法:
- 在此过程中解析一些输入并将其重要部分存储在 Map 中。
- 以表单形式显示解析后的输入(请参阅此示例图片)。表单字段由键命名并填充 Map 的值,而文本输入字段包含整个输入。
因此,如果用户输入/更改底部的文本,表单字段的内容也会因为构建 Map 的解析器语法中的代码操作(用作填写表单字段的输入)而改变。
但我们还想要另一个方向:如果用户更改了其中一个表单字段中的值,这些更改应该反映在底部的文本中。
我想使用 AST 创建然后操作来完成这个任务。我已经在我的语法中添加了树重写规则。但我不太确定如何在 Map、AST 和如何创建输出之间建立联系。
我什至走在正确的轨道上吗?还有其他想法吗?
编辑
所以我按照你的建议,把离开节点直接放到了一个可以更改的数据结构中,一切都很好。
但现在我还有另外两个问题:
- 如何添加令牌?输入中有可选部分,因此某些表单字段可能为空。如果我将表单字段更改为给定值,我必须在树中创建新节点。我该怎么做?我必须确定将新节点放在哪里......
- 如何删除令牌?因此,如果我将某个表单字段的值更改为“空”,则必须删除关联的节点,但这可能会影响周围的节点(例如,在列表中,每个标记后面都有逗号)。我真的不知道该怎么做。
这是我目前的语法:
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}
看起来像这样(黄色节点将始终存在,其他一切都是可选的)。因此,如果我在表单字段中将“refl”更改为“”,节点“refl”应该消失,而且它之前的“,”也会消失。如果我删除下面的“f” LEMMA_GRAMM
,整个子树必须消失(因为列表不能为空)。或者,如果我想向 中添加子语义TRANSLATION
,我必须TRANSLAT_SUBSEM
为花括号{{
和. 创建相应的节点和子节点}}
。
我真的不知道从哪里开始。我的树结构甚至对此有好处吗?我需要我自己的实现BaseTree
吗?或者它只是普通的Java?