總監:阿毛啊,下面咱們負責的項目你負責詞法、語法那塊的工作吧?
我:emmm........詞法語法我倒是大學有學過,編譯原理????大學學的就不好,難于上青天啊。。
總監:你覺得有什么問題嗎?
我:好的(內心一萬個拒絕),我前期先調研一下吧。
總監:好的這個功能比較難,好好用心啊。畫大餅開始。。。。
經過幾天的調研分析,antlr是最適合不過的了。下面咱們就一起學習一下吧。
ANTLR 官方網址 http://www.antlr.org/
ANTLR 官方 Github https://github.com/antlr/antlr4
大量語法文件例子 https://github.com/antlr/grammars-v4
Antlr是一款強大的語法分析器生成工具,可用于讀取、處理、執行和翻譯結構化的文本或二進制文件。它被廣泛的應用于學術領域和工業生產實踐,是眾多語言、工具和框架的基石。Twitter所使用Antlr進行語法分析,每天超過20億次查詢,Hadoop生態環境中的Hive、Pig、數據倉庫和分析系統所使用的分析系統都使用到了Antlr。
Antlr是用JAVA寫的語言識別工具,它用來聲明語言的語法,簡稱為“元語言”(meta-language)。
Antlr 語法識別一般分為二個階段:
1.詞法分析階段 (lexical analysis)
對應的分析程序叫做 lexer ,負責將符號(token)分組成符號類(token class or token type)
2.解析階段
根據詞法,構建出一棵分析樹(parse tree)或叫語法樹(syntax tree)
1.定制特定領域語言(DSL)
類似hibernate中的HQL,用DSL來定義要執行操作的高層語法,這種語法接近人可理解的語言,由DSL到計算機語言的翻譯則通過ANTLR來做,可在ANTLR的結構語言中定義DSL命令具體要執行何種操作。
2.文本解析 可利用ANTLR解析JSON,HTML,XML,EDIFACT,或自定義的報文格式。解析出來的信息需要做什么處理也可以在結構文件中定義。
3.數學計算 加減乘除,線性方程,幾何運算,微積分等等
/** Optional javadoc style comment */
grammar Name;
options {...}
import ... ;
tokens {...}
channels {...} // lexer only
@actionName {...}
rule1 // parser and lexer rules, possibly intermingled
...
ruleN
聲明語法頭,類似于java類的定義
grammar SPL;
選項,如語言選項,輸出選項,回溯選項,記憶選項等等
options { output=AST; language=Java; }
options { tokenVocab=MySqlLexer; }
動作(Actions)實際上是用目標語言寫成的、嵌入到規則中的代碼(以花括號包裹)。它們通常直接操作輸入的標號,但是他們也可以用來調用相應的外部代碼。屬性,到目前為止我的理解還不多,感覺像是C++中類里面的成員。常用屬性或動作說明:
這是核心,表示規則,以 “:” 開始, “;” 結束, 多規則以 "|" 分隔。
ID : [a-zA-Z0-9|'_']+ ; //數字
STR:'\'' ('\'\'' | ~('\''))* '\'';
WS: [ \t\n\r]+ -> skip ; // 系統級規則 ,即忽略換行與空格
sqlStatement
: ddlStatement
| dmlStatement | transactionStatement
| replicationStatement | preparedStatement
| administrationStatement | utilityStatement
;
/**
* This grammar is an example illustrating the three kinds
* of comments.
*/
grammar T;
/* a multi-line
comment
*/
/** This rule matches a declarator for my language */
decl : ID ; // match a variable name
ID, LPAREN, RIGHT_CURLY // token names
expr, simpleDeclarator, d2, header_file // rule names
grammar Dsl; //定義規則文件grammar
@header { //一種action,定義生成的詞法語法解析文件的頭,當使用java的時候,生成的類需要包名,可以在這里統一定義
package antlr;
}
//parsers
sta:(sql ender)*; //定義sta規則,里面包含了*(0個以上)個 sql ender組合規則
ender:';'; //定義ender規則,是一個分號
sql //定義sql規則,sql規則有兩條分支:select/load
: SELECT ~(';')* as tableName //select語法規則,以lexer SELECT開頭, 以as tableName 結尾,其中as 和tableName分別是兩個parser
| LOAD format '.' path as tableName //load語法規則,大致就是 load json.'path' as table1,load語法里面含有format,path, as,tableName四種規則
; //sql規則結束符
as: AS; //定義as規則,其內容指向AS這個lexer
tableName: identifier; //tableName 規則,指向identifier規則
format: identifier; //format規則,也指向identifier規則
path: quotedIdentifier; //path,指向quotedIdentifier
identifier: IDENTIFIER | quotedIdentifier; //identifier,指向lexer IDENTIFIER 或者parser quotedIdentifier
quotedIdentifier: BACKQUOTED_IDENTIFIER; //quotedIdentifier,指向lexer BACKQUOTED_IDENTIFIER
//lexers antlr將某個句子進行分詞的時候,分詞單元就是如下的lexer
//keywords 定義一些關鍵字的lexer,忽略大小寫
AS: [Aa][Ss];
LOAD: [Ll][Oo][Aa][Dd];
SELECT: [Ss][Ee][Ll][Ee][Cc][Tt];
//base 定義一些基礎的lexer,
fragment DIGIT:[0-9]; //匹配數字
fragment LETTER:[a-zA-Z]; //匹配字母
STRING //匹配帶引號的文本
: '\'' ( ~('\''|'\\') | ('\\' .) )* '\''
| '"' ( ~('"'|'\\') | ('\\' .) )* '"'
;
IDENTIFIER //匹配只含有數字字母和下劃線的文本
: (LETTER | DIGIT | '_')+
;
BACKQUOTED_IDENTIFIER //匹配被``包裹的文本
: '`' ( ~'`' | '``' )* '`'
;
//--hiden 定義需要隱藏的文本,指向channel(HIDDEN)就會隱藏。這里的channel可以自定義,到時在后臺獲取不同的channel的數據進行不同的處理
SIMPLE_COMMENT: '--' ~[\r\n]* '\r'? '\n'? -> channel(HIDDEN); //忽略行注釋
BRACKETED_EMPTY_COMMENT: '/**/' -> channel(HIDDEN); //忽略多行注釋
BRACKETED_COMMENT : '/*' ~[+] .*? '*/' -> channel(HIDDEN) ; //忽略多行注釋
WS: [ \r\n\t]+ -> channel(HIDDEN); //忽略空白符
// 匹配其他的不能使用上面的lexer進行分詞的文本
UNRECOGNIZED: .;
1、Listener (觀察者模式,通過結點監聽,觸發處理方法)
2、Visitor (訪問者模式,主動遍歷)
下載Java安裝
我使用的是Java8,這里就不詳細介紹Java的安裝了。
1.下載antlr-4.7.2-complete.jar
https://www.antlr.org/download/antlr-4.7.2-complete.jar
Linux下的安裝方式:
$ cd /usr/local/lib
$ sudo curl -O https://www.antlr.org/download/antlr-4.7.2-complete.jar
2.新建運行腳本 antlr4.bat 和 grun.bat,放置于任意目錄,如 E:/tools/antlr4
antlr4.bat 內容:
java org.antlr.v4.Tool %*
grun.bat 內容:
java org.antlr.v4.gui.TestRig %*
注:antlr依賴于java,如果java環境變量沒有設置,請先行設置好。
3.設置antlr4的系統環境變量
Windows環境配置:
E:/tools/antlr4/antlr-4.7.2-complete.jar
E:/tools/antlr4
Windows環境變量配置
Linux及Mac:
// 設置環境變量
$ vim .bash_profile
$ export CLASSPATH=".:/usr/local/lib/antlr-4.7.2-complete.jar:$CLASSPATH"
$ alias antlr4='java -jar /usr/local/lib/antlr-4.7.2-complete.jar'
$ alias grun='java org.antlr.v4.gui.TestRig'
$ wq
$ source .bash_profile
$ antlr4
ANTLR Parser Generator Version 4.7.2
-o ___ specify output directory where all output is generated
-lib ___ specify location of grammars, tokens files
-atn generate rule augmented transition network diagrams
-encoding ___ specify grammar file encoding; e.g., euc-jp
-message-format ___ specify output style for messages in antlr, gnu, vs2005
-long-messages show exception details when available for errors and warnings
-listener generate parse tree listener (default)
-no-listener don't generate parse tree listener
-visitor generate parse tree visitor
-no-visitor don't generate parse tree visitor (default)
-package ___ specify a package/namespace for the generated code
-depend generate file dependencies
-D<option>=value set/override a grammar-level option
-Werror treat warnings as errors
-XdbgST launch StringTemplate visualizer on generated code
-XdbgSTWait wait for STViz to close before continuing
-Xforce-atn use the ATN simulator for all predictions
-Xlog dump lots of logging info to antlr-timestamp.log
-Xexact-output-dir all output goes into -o dir regardless of paths/package
$ grun
java org.antlr.v4.gui.TestRig GrammarName startRuleName
[-tokens] [-tree] [-gui] [-ps file.ps] [-encoding encodingname]
[-trace] [-diagnostics] [-SLL]
[input-filename(s)]
Use startRuleName='tokens' if GrammarName is a lexer grammar.
Omitting input-filename makes rig read from stdin.
安裝成功
$ mkdir test
$ cd test/
$ vim Hello.g4
輸入:
// Define a grammar called Hello
grammar Hello;
r : 'hello' ID ; // match keyword hello followed by an identifier
ID : [a-z]+ ; // match lower-case identifiers
WS : [ \t\r\n]+ -> skip ; // skip spaces, tabs, newlines
$ wq! // 保存
$ antlr4 Hello.g4
$ ls
Hello.g4 HelloBaseListener.java HelloLexer.tokens
Hello.interp HelloLexer.interp HelloListener.java
Hello.tokens HelloLexer.java HelloParser.java
$ javac Hello*.java
$ ls
Hello.g4 HelloLexer.java
Hello.interp HelloLexer.tokens
Hello.tokens HelloListener.class
HelloBaseListener.class HelloListener.java
HelloBaseListener.java HelloParser$RContext.class
HelloLexer.class HelloParser.class
HelloLexer.interp HelloParser.java
$ grun Hello r -gui // 按回車
hello nihao // 輸入這個,再按回車
^D // 按ctrl+D 就出現gui圖形界面了
GUI界面
java編譯過程
和生成Java代碼類似,不同的地方在于編譯g4文件命令:
antlr4 -Dlanguage=Python3 -visitor Expr.g4
這樣就會生成python代碼:
? antlr4 -Dlanguage=Python3 Hello.g4
? ls
Hello.g4 Hello.tokens HelloLexer.py HelloListener.py
Hello.interp HelloLexer.interp HelloLexer.tokens HelloParser.py
python編譯
當然還可以生成其他代碼,感興趣的可以嘗試學一下。
上面就是我在學習Antlr中所了解的知識,歡迎大家指正,一起學習,一起進步。
關注私信小編,Antlr權威指南分享給你,另外小編會不定時分享一些學習知識點。一起學習吧。
在本教程中,我們學習如何ant在 Debian 11 上安裝。
Apache Ant 是一個 Java 庫和命令行工具,其任務是驅動構建文件中描述的進程作為相互依賴的目標和擴展點。Ant 的主要已知用途是構建 Java 應用程序。Ant 提供了許多內置任務,允許編譯、組裝、測試和運行 Java 應用程序。Ant 也可以有效地用于構建非 Java 應用程序,例如 C 或 C++ 應用程序。更一般地說,Ant 可用于試驗任何類型的過程,這些過程可以用目標和任務來描述。這個包包含腳本和核心任務庫。
ant在 Debian 11上安裝有三種方式。我們可以使用apt-get,apt和aptitude. 在以下部分中,我們將描述每種方法。您可以選擇其中之一。
apt-get使用以下命令更新 apt 數據庫。
sudo apt-get update
更新 apt 數據庫后,我們可以ant通過apt-get運行以下命令進行安裝:
sudo apt-get -y install ant
apt使用以下命令更新 apt 數據庫。
sudo apt update
更新 apt 數據庫后,我們可以ant通過apt運行以下命令進行安裝:
sudo apt -y install ant
如果你想遵循這個方法,你可能需要先安裝aptitude,因為 aptitude 通常不會在 Debian 上默認安裝。aptitude使用以下命令更新 apt 數據庫。
sudo aptitude update
更新 apt 數據庫后,我們可以ant通過aptitude運行以下命令進行安裝:
sudo aptitude -y install ant
要僅卸載ant軟件包,我們可以使用以下命令:
sudo apt-get remove ant
要卸載antDebian 11 不再需要的及其依賴項,我們可以使用以下命令:
sudo apt-get -y autoremove ant
要從 Debian 11 中刪除ant配置和數據,我們可以使用以下命令:
sudo apt-get -y purge ant
我們可以使用以下命令刪除ant配置、數據及其所有依賴項,我們可以使用以下命令:
sudo apt-get -y autoremove --purge ant