我有一個更一般的問題。操縱AST來改變輸入文字
我目前正在使用ANTLR V3.4項目 - 這裏是我們的理念:
- 解析某些輸入,並在地圖的過程中存儲其重要組成部分。
- 在表單中顯示解析的輸入(請參閱此Example Picture)。表單字段由鍵命名並填充了Map的值,而文本輸入字段包含整個輸入。
所以,如果用戶輸入/改變在底部的文本,格式字段的內容也將改變,因爲在解析器語法即建立其被用作輸入來填充地圖(代碼動作的表單域)。
但是我們也想要另一個方向:如果用戶在其中一個表單域中更改了值,那麼這些更改應該反映在底部的文本中。
我想過使用AST創建,然後操縱來完成這項任務。我已經將樹重寫規則添加到了我的語法中。但我不太清楚如何在Map,AST和如何創建輸出之間建立連接。
我是否在正確的軌道?任何其他想法?
編輯
所以我跟着你的建議,並直接把假節點爲可以改變的數據結構,一切都很好。
但是現在我有其他2個問題:
- 如何添加令牌?輸入中有可選部分,因此某些表單域可能爲空。如果我將表單字段更改爲給定值,則必須在樹中創建新節點。我將如何做到這一點?我必須確定在哪裏放置新節點...
- 我如何刪除令牌?因此,如果我將某些表單字段的值更改爲'空',則必須刪除關聯的節點,但這可能會影響周圍的節點(例如,在每個標記之後的逗號中都有逗號)。我真的不知道該怎麼做。
這是我目前的語法:
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?
你已經看過Eclipse JDT嗎?他們不在那裏使用EMF。所以他們可能會做一些類似的事情的機會很大。 – SpaceTrucker
讓Map將鍵關聯到相應的AST節點如何?您可以從節點獲取初始值並直接進行更新。 – user1201210
聽起來很有希望,我會試試看。 – codebat