基于JavaCC的语法描述
只要为JavaCC描述"语句"、“表达式”、“函数调用” 这样的语法单位各自是由怎样的token序列构成的,就能够对该语法进行分析。
例如,最简单的赋值表达式可以描述为 "符号" = "表达式"
的排列。换言之,如果存在 "符号" = "表达式"
表达式这样的排列,那就是赋值表达式。
这个规则在 JavaCC 中表示成下面这样
assign(): //定义赋值表达式,名字任取
{}
{
<IDENTIFIER> "=" expr() //<IDENTIFIER> 对应 token 标识符,"=" 对应 "=" token,expr() 对应表达式,名字可以任取
}
expr(): //表达式 expr() 自身也是由多个 token 构成的,这样的情况下需要进一步对 expr() 的规则进行描述
{}
{ expr() "+" expr()
或 expr() "-" expr()
或 expr() "*" expr()
......
}
像这样写好所有语法单位的规则之后,基于 JavaCC 的解析器的描述也就完成了。
终端符和非终端符
JavaCC 中将刚才的“语句”、“函数调用”、“表达式” 等非 token 的语法单位称为非终端符。
JavaCC 中除了扫描器中定义的 token 以外,"="、"+"、"==" 这样的字符串字面量也可以作为终端符来使用。
种类 | 含义 | 例 |
---|---|---|
终端符 | token | 、、"="、"==" |
非终端符 | 由终端符排列组成的语法单位 | stmt()、expr()、assign() |
JavaCC 的 EBNF 表示法
JavaCC使用EBNF(Extended Backus-Naur-Form)的表示法来描述语法规则
种类 | 例子 |
---|---|
终端符 | 或"," |
非终端符 | name() |
连接 | |
重复0次或多次 | (","expr())* |