CDM之ANTLR學習

      網友投稿 829 2025-03-31

      ANTLR是什么

      ANTLR是一個解析器生成工具,可以根據你書寫的文法文件,自動生成可以解析該文法的解析器(Parser).其強大的功能遠不止這些.

      文法文檔(Grammar Lexicon)

      Lexicon是按ANTLR規范書寫的文件,在這個文件中指定你要解析的文法,ANTLR再根據這個文件生成對應的解析器.

      標識符(Identifiers)

      詞法單元和詞法規則通常以大寫字母命名

      解析規則(parser rule) 以小寫字母開頭命名(駝峰命名法)

      例如:

      1

      2

      ID, LPAREN, RIGHT_CURLY //token names/rule

      expr, simpleDclarator, d2, header_file //rule names

      ANTLR還支持unicode編碼的字符命名

      文字(Literals)

      ANTLR不區分字符和字符串.所有的字符串(這里是指出現在源文件中的需要被識別的字符串)都是由單引號引用起來的字符,但是像這樣的字符串中不包括正則表達式.支持unicode和轉義符號例如

      1

      2

      3

      4

      ',' , 'if', '>=',

      ' \''//轉義的單引號

      '\u00E8' //法語中的字符è

      '\n', '\r' //換行 回車

      動作(Actions)

      動作是用目標語言書寫的代碼塊.嵌入的代碼可以出現在:

      @header?@members這樣的命名動作中

      解析規則和詞法規則中

      異常捕獲中

      解析規則的屬性部分(返回值,參數等)

      一些規則可選元素中

      關鍵字(Keywords)

      ANTLR中有一些保留關鍵字,例如:

      1

      import,?fragment,?lexer,?parser,?grammar,?returns,?locals,?throws,?catch,?finally,?mode,?options,?tokens

      語法結構(Grammar Structure)

      語法結構如下

      |Grammar |

      | ————- |

      | /Optional javadoc style comment*/|

      |?grammer?Name; |

      |?options?{…}; |

      |?import?…; |

      |?tokens?{…}; |

      |?channels?{…}; |

      |?@actionName** {…}; |

      | |

      | rule1 //parser and lexer rules |

      | … |

      | ruleN |

      文件命名必須和grammar命名相同,如?grammar T,文件名必須命名為T.g4.

      options,imports,token,action的聲明順序沒有要求,但一個文件中options,imports,token最多只能聲明一次.grammar是必須聲明的,同時必須至少聲明一條規則(rule),其余的部分都是可選的.

      規則(rules)

      規則的聲明遵循以下格式:

      1

      2

      3

      4

      ruleName : alternative1 | ... | alternativeN ;

      //定義類型

      type : 'int' | 'unsigned' | 'long'

      引入(imports)

      ANTLR中的引入機制類似于OO中的繼承.它會從引入的文件繼承所有的規則,詞法單元,動作.然后主文件中的元素會”覆蓋”引入文件中的重名元素.

      嵌套引用的合并規則比較復雜,詳見官方文檔

      詞法單元(Tokens Section)

      1

      tokens?{Token1?...?TokenN}

      例如為向量表示定義虛詞法單元:

      1

      2

      3

      4

      5

      6

      7

      8

      9

      grammar VecMathAST

      options{output=AST;}

      tokens{VEC;}

      statlist : stat+ ;

      stat : ID '=' expr -> ^('=' ID expr)

      | 'print' expr -> ^('print' expr);

      expr : multExpr ('+' ^ multExpr)*;

      multExpr : primary (('*'^|'.'^) primary)*;

      primary : INT | ID | '[' expr (',' expr)* ']' -> ^(VEC expr+);

      動作(Actions at the Grammar Level)

      針對java,有兩個已經定義好的action:header和members

      @header在生成的目標代碼中的類定義之前注入代碼

      @members在生成的目標代碼中的類定義里注入代碼(例如類的屬性和方法)

      1

      2

      3

      4

      5

      6

      7

      8

      9

      10

      11

      12

      13

      grammar Count;

      @header {

      pacakage foo;

      }

      @members{

      int count = 0;

      }

      list @after{System.out.println(count+"ints");} : INT {count++;} (',' INT {count++})*

      ;

      INT: [0-9]+;

      解析器規則(Parser Rules)

      解析器由一組解析器規則組成.java應用通過調用生成的規則函數(每個規則會生成一個函數)來啟動解析.

      基本形式如下,用?|?操作符分割多個選項

      1

      stat?:?restat?|?'break'?';'?|?'continue'?';'?;

      可選標簽(Alternative Labels)

      可以在規則中添加標簽,ANTLR會根據標簽生成與規則相關的解析樹的事件監聽函數,使我們更加精準的控制解析過程.用?#?操作符定義一個標簽

      用法如下:

      1

      2

      3

      grammar T;

      stat: 'return' e ';' # Return

      | 'break' ';' # Break

      ANTLR會為每個標簽生成一個rule-context類.

      1

      2

      3

      4

      5

      6

      public interface AListener extends ParseTreeListener {

      CDM之ANTLR學習

      void enterReturn(AParser.ReturnContext ctx);

      void exitReturn(AParser.ReturnContext ctx);

      void enterBreak(AParser.BreakContext ctx);

      void exitBreak(AParser.BreakContext ctx);

      }

      同一個標簽可以加在多個規則選項上(multiple alternatives),但是標簽命名不可以和規則名沖突

      規則上下文對象(Rule Context Objects)

      ANTLR為每個規則生成一個上下文對象,通過這個對象可以訪問規則定義中的其他規則的引用.根據規則定義中的其他規則的引用數量不同,生成對象中包含的方法也不同.例如:

      1

      2

      3

      4

      5

      6

      7

      inc : e '++';

      //generates this context class

      public static class IncContext extends ParserRuleContext {

      public EContext e() { ... } // return context object associated with e

      ...

      }

      1

      2

      3

      4

      5

      6

      7

      8

      field : e '.' e;

      //generates this context class

      public static class FieldContext extends ParserRuleContext {

      public EContext e(int i) { ... } // get ith e context

      public List e() { ... } // return ALL e contexts

      ...

      }

      規則元素標簽(Rule Element Labels)

      可以用?=?操作符為規則中的元素添加標簽,這樣會在規則的上下文對象中添加元素的字段.

      例如:

      1

      2

      3

      4

      5

      6

      7

      8

      9

      stat: 'return' value=e ';' # Return //將e的context作為一個字段添加到 ReturnContext中

      | 'break' ';' # Break

      ;

      //generates context class

      public static class ReturnContext extends StatContext {

      public EContext value;

      ...

      }

      +=?操作符可以很方便的記錄大量的token或者規則的引用

      1

      2

      3

      4

      5

      6

      array : '{' el+=INT (',' el+=INT)* '}' ;

      //ANTLR generates a List field in the appropriate rule context class:

      public static class ArrayContext extends ParserRuleContext {

      public List el = new ArrayList();

      ...

      }

      規則元素(Rule ELements)

      規則元素指定了解析器在具體時刻應該執行什么任務.元素可以是規則(rule),?詞法單元(token),?字符串文字(string literal)等

      T?token

      ‘literal’ ? ? ?字符串文字

      r ? ? ?規則

      r[args] ? ? ?向規則函數中傳遞參數,參數的書寫規則是目標語言,用逗號分隔

      .?通配符

      {action} ? ? ?動作,在元素的間隔中執行

      {p} ? ? ?謂詞

      支持邏輯非操作符:~

      子規則

      規則中包含的可選塊稱為子規則(被封閉在括號中).子規則也可以看做規則(rule),但是沒有顯式的命名.子規則不能定義局部變量,也沒有返回值.如果子規則只有一個元素,括號可以省略.

      子規則有四種

      例如:

      (x|y|z) ? ? ?只匹配一個選項

      (x|y|z)? ? ? ?匹配一個或者不匹配

      (x|y|z)* ? ? ?匹配零次或多次

      (x|y|z)+ ? ? ?匹配一次或多次

      參考:

      https://developer.ibm.com/zh/articles/j-lo-antlr/

      https://theantlrguy.atlassian.net/wiki/display/ANTLR4/ANTLR+4+Documentation

      http://yijun1171.github.io/2015/03/30/ANTLR4%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0-%E8%AF%AD%E6%B3%95%E5%AD%97%E5%85%B8-Grammar-Lexicon

      云數據遷移 CDM 面向對象編程

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:如何在WPS文本中輸入帶圓圈的文本就是圈出一個數字或符號
      下一篇:粘貼表格怎么保留原格式(word粘貼表格怎么保留原格式)
      相關文章
      亚洲精品无码少妇30P| 狠狠色伊人亚洲综合网站色| 日韩亚洲人成在线综合| 亚洲精品456人成在线| 亚洲婷婷综合色高清在线| 91亚洲国产成人久久精品网站| 亚洲AV中文无码字幕色三| 久久亚洲精品视频| 久久国产亚洲精品麻豆| 亚洲国产精品一区第二页 | 亚洲国产精品第一区二区三区| 337p日本欧洲亚洲大胆人人| 久久亚洲AV成人无码国产电影 | 亚洲日韩看片无码电影| 亚洲www77777| 亚洲欧洲无卡二区视頻| 亚洲gay片在线gv网站| 亚洲av无码专区首页| 亚洲AⅤ无码一区二区三区在线 | 精品国产人成亚洲区| 久久精品亚洲福利| 亚洲精品少妇30p| 久久精品亚洲综合| 亚洲福利一区二区| 亚洲乱码中文字幕小综合| 亚洲最大福利视频| 亚洲成aⅴ人片久青草影院按摩| 亚洲jizzjizz少妇| 亚洲午夜精品第一区二区8050| jlzzjlzz亚洲乱熟在线播放| 亚洲午夜无码久久久久| 亚洲av无码一区二区三区乱子伦| 亚洲人成影院在线| 亚洲成a人片毛片在线| 亚洲人成未满十八禁网站| 国产一区二区三区亚洲综合| 国产精品亚洲高清一区二区 | 亚洲jjzzjjzz在线播放| 亚洲日韩AV一区二区三区四区| 久久亚洲中文字幕无码| 亚洲乱码日产精品a级毛片久久|