使用JavaCC從token序列中識別出"語句" 「表達式」 「函數調用」 等語法單位的方法。java
只要爲JavaCC描述「語句」 「表達式」 「函數調用」 這樣的語法單位各自是由怎樣的token序列構成的,就可以對該語法進行分析(parse)。函數
例如:最簡單的賦值表達式能夠描述爲「符號」 「 「=」 」 」表達式「 的排列。 換言之, 若是存在」符號「 」 」=「 「 」表達式「 這樣的排列 那就是賦值表達式。這個規則在JavaCC中表示成下面這樣:spa
assign(): {} { <IDENTIFIER> "=" expr() }
assign()對應賦值表達式,<IDENTIFIER>對應token標示符,"="對應"="token。
像<IDENTIFIER>這樣已經在掃描器中定義的token,在描述解析器時能夠直接使用。其餘的如"="這樣的固定字符串也由於能夠表示token,因此也能在規則中使用。 另外,表達式expr()自身也是多個token構成的,這樣的狀況下須要進一步對expr()的規則進行描述,如下是僞描述:code
expr(): {} { expr() "+" expr() 或expr() "-" expr() 或expr() "*" expr() .. . }
JavaCC中將"語句" "函數調用" "表達式" 等非token的語法單位稱爲非終端符,並將非終端符像java的函數調用同樣在後面加上括號寫成stmt()或expr()。
終端符能夠概括爲token。使用在掃描器中定義的名稱,能夠寫成<INDENTIFIER>或<LONG>。而且JavaCC中除了掃描器中定義的token之外, "="、"+"、"==" 這樣的字符串字面量也能夠做爲終端符來使用orm
種類 | 含義 | 例 |
---|---|---|
終端符 | token | <IDENTIFIER>、<LONG>、"="、"==" |
非終端符 | 由終端符排列組成的語法單位 | stmt()、expr()、assign() |
在畫語法時,終端符位於樹的枝幹的末端(終端),非終端符因爲是由其餘符號的列組成的,因此位於分叉處。token
JavaCC使用EBNF(Extended Backus-Naur-Form)的表示法來描述語法規則。下表中羅列了JavaCC的解析器生成所使用的EBNF表示法。字符串
種類 | 例子 |
---|---|
終端符 | <IDENTIFIER>或"," |
非終端符 | name() |
鏈接 | <UNISGNED><LONG> |
重複0次或屢次 | (","expr())* |
重複1次或屢次 | (stmt())+ |
選擇 | <CHAR>丨<SHORT>丨<INT>丨<LONG> |
能夠省略 | [<ELSE>stmt()] |
鏈接是指特定符號相連續的模式。例如C語言continue語句是保留字continue和分號的排列。JavaCC中將該規則寫成以下形式:string
<CONTINUE> ";"
<CONTINUE>是表示保留字continue的終端符,「:」是表示字符自身的終端符。it
下面的寫法表示0個或多個語句排列:io
(stmt())*
下面的例子,函數的參數是由逗號分隔的表達式排列組成的,即expr以後排列着0個或多個逗號和expr的組合:
expr() ("," expt())*
(stmt())+
上面的代碼描述了非終端符stmt()重複1次或屢次。
選擇即爲從多個選項中選擇1個的規則。例如cflat的類型由void、char、unsigned、char等:
<VOID> | <CHAR> | <UNSIGNED> | <CHAR> | ...
定義變量時能夠設置初始值也能夠不設置,這種在JavaCC中能夠寫成:
storage() typeref() name() ["=" expr()] ";"