中文編程 "知乎專欄" 原文 "地址" (前文 "通用型的中文編程語言探討之一: 高考" , 即使是這"第一步", 即使一切順利達到列出的功能恐怕也需要個人數年的業餘時間. 看到不少乎友都遠更有資本和實力更快速地完成這一工程. 希望隨時告知類似項目, 省得在下作無用功) 初步打算用Antlr4生成J ...
(前文通用型的中文編程語言探討之一: 高考, 即使是這"第一步", 即使一切順利達到列出的功能恐怕也需要個人數年的業餘時間. 看到不少乎友都遠更有資本和實力更快速地完成這一工程. 希望隨時告知類似項目, 省得在下作無用功)
初步打算用Antlr4生成Java實現的詞語法分析器, 主要是出於減少工作量的考慮, 但相應的需要深入學習這個工具. 根據至今看到的相關文檔以及Antlr項目本身, 感覺還蠻實用, 可持續性也不錯, 這些學習應該不會白費.
之前沒有實驗過它對錯誤語法的處理. 本文實現了編程語言試驗之Antlr4+Java實現"圈2"的Visitor版本. 再添加了定製的詞法語法錯誤處理. 源碼在program-in-chinese/quan5
語法最簡單, 只包含一個數:
grammar 圈5;
程式 : T數;
T數 : [0-9]+ ;
T空白 : [ \n\t]+ -> skip;
定製的語法錯誤處理器, 只有報告功能:
public class 語法錯誤監聽器 extends BaseErrorListener {
@Override
public void syntaxError(Recognizer<?, ?> 識別器, Object 問題符號, int 行, int 字元在行中位置, String 信息,
RecognitionException 例外) {
List<String> 規則棧 = ((Parser) 識別器).getRuleInvocationStack();
Collections.reverse(規則棧);
System.err.println("[語法錯誤] 規則棧: " + 規則棧);
System.err.println("行" + 行 + "列" + 字元在行中位置 + "非法符號: " + 問題符號 + ". 原始原因:" + 信息);
}
}
下麵是為語法分析器添加定製的錯誤分析(先除去預設的錯誤監聽器):
圈5Parser 語法分析器 = new 圈5Parser(new CommonTokenStream(詞法分析器));
語法分析器.removeErrorListeners();
語法分析器.addErrorListener(語法錯誤處理);
類似的也可以為詞法分析器添加錯誤處理器. 其中為了取得錯誤的詞, 沒有找到現成的介面, 於是摘取了它源碼一部分. 初步的感覺是, 雖然API不一定很完善(很有可能是自己不熟悉工具導致的), 但不少公開屬性可以比較方便定製:
public class 詞法錯誤監聽器 extends BaseErrorListener {
@Override
public void syntaxError(Recognizer<?, ?> 識別器, Object 問題符號, int 行, int 字元在行中位置, String 信息,
RecognitionException 例外) {
Lexer 詞法分析器 = (Lexer)識別器;
// 摘自org.antlr.v4.runtime.Lexer.notifyListeners
String 文本 = 詞法分析器._input.getText(Interval.of(詞法分析器._tokenStartCharIndex, 詞法分析器._input.index()));
String 錯詞 = 詞法分析器.getErrorDisplay(文本);
System.err.println("[詞法錯誤] 行" + 行 + "列" + 字元在行中位置 + "錯誤詞: " + 錯詞);
}
}
下麵是一個語法有誤的文件:
a
分析後的報錯輸出:
[詞法錯誤] 行2列3錯誤詞: a
[語法錯誤] 規則棧: [程式]
行2列4非法符號: [@0,5:4='<EOF>',<-1>,2:4]. 原始原因:missing T at '<EOF>'