1. 程式人生 > >程式語言試驗之Antlr4+Java實現"圈2"

程式語言試驗之Antlr4+Java實現"圈2"

知乎原文

此文涉及的原始碼版本: program-in-chinese/quan2

宣告 程式碼來源 How to Create Language Using Antlr4

本作主要作為學習Antlr, 以及實踐中文命名之用. 目標不是一個實用的程式語言.

個人感覺這樣可以比較容易的用原型來嘗試和演示不同語法設計, 如果有更簡單的途徑請不吝賜教. 歡迎各種自行修改~碰到任何問題也歡迎一同探討.

下面是"圈2"語言的示例程式碼:

開始
    使 甲 為 5
    使 乙 為 10
    加 3 到 乙
    加 乙 到 甲
    加 甲 到 乙
    列印 乙
    列印 3
結束

附上需要自行編寫的三個檔案:
Antlr4的語法定義檔案:

按照README說明, Antlr可以據此自動生成四個分析器相關類檔案. T字首是由於Antlr約定大寫開頭是Token定義. 識別符號支援中文.

grammar 圈2;
程式   : '開始' 宣告+ '結束';
          
宣告 : 賦值 | 加 | 列印 ;

賦值    : '使' T識別符號 '為' (T數 | T識別符號) ;
列印     : '列印' (T數 | T識別符號) ;
加       : '加' (T數 | T識別符號) '到' T識別符號 ;

T識別符號     : ('a' .. 'z' | 'A' .. 'Z' | '\u4E00'..'\u9FA5' | '\uF900'..'\uFA2D')+ ;
T數 : [0-9]+ ;
T空白     : [ \n\t]+ -> skip;

定製監聽器:

通過對每種語句分析後進行對應處理, 實質上起了直譯器的作用.

public class 定製監聽器 extends2BaseListener {

  private Map<String, Integer> 變量表;

  public 定製監聽器() {
    變量表 = new HashMap<>();
  }

  @Override
  public void exit賦值(賦值Context 上下文) {
    // 賦值語句分析結束時執行此方法

    String 變數名 = 上下文.T識別符號(0).getText();
// 如果語句中有兩個變數(識別符號), 那麼取第二個變數的值, 否則取數的值 int= 上下文.T識別符號().size() > 1 ? 變量表.get(上下文.T識別符號(1).getText()) : Integer.parseInt(上下文.T數().getText()); // 更新變數值 變量表.put(變數名,); } @Override public void exit加(加Context 上下文) { // 加語句分析結束時執行此方法 String 變數名 = 上下文.T識別符號().size() > 1 ? 上下文.T識別符號(1).getText() : 上下文.T識別符號(0).getText(); int 新增值 = 上下文.T識別符號().size() > 1 ? 變量表.get(上下文.T識別符號(0).getText()) : Integer.parseInt(上下文.T數().getText()); 變量表.put(變數名, 變量表.get(變數名) + 新增值); } @Override public void exit列印(列印Context 上下文) { // 列印語句分析結束時執行此方法 String 輸出 = 上下文.T識別符號() == null ? 上下文.T數().getText() : 變量表.get(上下文.T識別符號().getText()).toString(); System.out.println(輸出); } }

執行器:

讀取檔案輸入, 呼叫附著了定製監聽器的分析器

public class 執行器 {
  public static void main(String[] 引數) {
    try {
      ANTLRInputStream 輸入 = new ANTLRInputStream(new FileInputStream(引數[0]));2Lexer 詞法分析器 = new2Lexer(輸入);2Parser 語法分析器 = new2Parser(new CommonTokenStream(詞法分析器));
      語法分析器.addParseListener(new 定製監聽器());

      // 開始分析
      語法分析器.程式();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
}

尚未探索如何用Antlr4實現無空格語法設計(不允許識別符號中出現關鍵字應該可以做到, 但那樣限制太多)