2013-04-23 47 views
0

我想寫詞法分析器/解析器R6RS,我只能和基準跳躍評論基準跳過評論「#;」同時使解析器R6RS與ANTLR4

這裏是我的詞法/語法規則的一些部分:

BOOLEAN: '#t' | '#f' | '#T' | '#F'; 
NUMBER: DIGIT+; // TODO: incomplete 
CHAR: '#\\' CHARNAME | '#\\x' HEXDIGIT+ | '#\\' . ; 
STRING: '"' STRELEMENT* '"'; 
IDENTIFIER: INITIAL SUBSEQUENT* | PERCULIAR_ID; 

COMMENT: (';' .*? LINE_ENDING | '#!r6rs') -> skip; 
NESTED_COMMENT: '#|' (NESTED_COMMENT | ~[#|] | ('|' ~'#') | ('#' ~'|'))* '|#' -> skip; 

datum: lexemeDatum 
    | compoundDatum; 
compoundDatum: list 
      | vector 
      | bytevector; 

// (rest omitted...) 

現在,我想寫如skipDatum: '#;' datum -> skip。不幸的是,解析器規則不允許->skip。由於詞法分析器規則不能引用解析器規則,所以SKIPDATUM: '#;' datum -> skip都不起作用。

在我看來,雖然「註釋掉」是詞法分析器的責任,「構建數據」是解析器的責任,但關於#;的規則都需要。

這是我目前的解決方案:

skipDatum: '#;' datum; 

list: '(' (datum|skipDatum)* ')' #ProperListDatum 
    | '[' (datum|skipDatum)* ']' #ProperListDatum 
    | '(' skipDatum* datum (datum|skipDatum)* '.' skipDatum* datum skipDatum* ')' #ImproperListDatum 
    | '[' skipDatum* datum (datum|skipDatum)* '.' skipDatum* datum skipDatum* ']' #ImproperListDatum 

雖然這是工作,它似乎很醜陋;我真的想寫規則使用datum,我總是要寫像skipDatum* datum skipDatum*

有沒有更好的解決方案?提前致謝。

回答

0

你可以使用這樣的東西。

datum 
    : SKIP_DATUM? ... 
    ; 

SKIP_DATUM : '#;'; 

這將需要執行以下檢查每次在生成的代碼使用DatumContext時間,同時簡化了語法。

if (ctx.SKIP_DATUM() != null) { 
    // handle skipped datum here (return?) 
} 
+0

雖然它看起來很有效,但它看起來像我們移動到'訪客'類的'醜'。當我繼續找到更好的方法時,我會嘗試這種方法。感謝你的回答。 – Venusaur 2013-04-23 15:37:08

+0

我決定在解析器規則上保留「複雜的工作」,但藉助謂詞如:'list:'['(d1 + = datum | skipDatum)+'。' (d2 + = datum | skipDatum)+']'{$ d1.size()> 0 && $ d2.size()== 1}? #ImproperListDatum'。我沒有注意到我可以在我的規則文件中插入一些「代碼」。雖然我沒有按照你的建議,但謝謝你的回答。 – Venusaur 2013-04-26 01:46:15