前言
本系列的文章的宗旨是讓大家能夠寫出自己的編譯器
前幾節文章只討論到了詞法分析和LL文法分析
Lex 和yacc這兩個工具是經典的詞法分析和語法分析工具
首先聲明我不是一個JAVA專家
Javacc 的獲取同lex和yacc一樣
Javacc 的原理
Javacc 可以同時完成對text的詞法分析和語法分析的工作
Javacc 的輸入文件
Javacc 的輸入文件格式做得比較簡單
Javacc 的輸入文件中
下面我們來看看Javacc中自帶的example中的例子
例
這個例子可以在javacc
PARSER_BEGIN(Simple
public class Simple
public static void main(String args[]) throws ParseException {
Simple
parser
}
}
PARSER_END(Simple
void Input() :
{}
{
MatchedBraces() (
}
void MatchedBraces() :
{}
{
}
設置好javacc的bin目錄後
javacc Simple
然後 javacc 就會為你生成下面幾個 java 源代碼文件
Simple
Simple
Simple
SimpleCharStream
Token
TokenMgrError
其中Simple
class Simple
PARSER_END(Simple
但是必須清楚的是
PARSER_END 下面的定義就是文法非終結符號的定義了
Simple
Input
MatchedBraces
從它的定義我們可以看到
比如 Input 的過程
void Input() :
{}
{
MatchedBraces() (
}
在定義 void Input 後面記住需要加上一個冒號
第一個 {} 中的代碼是定義數據
每個產生式之間用
注意
Input
中 (
而 <EOF> 是 javacc 系統定義的記號 (TOKEN)
除了 <EOF>
每個非終結符號 (Input 和 MatchedBraces) 都會在 javacc 生成的 Simple
例
在 javacc 提供的 example 裡面沒有
在大家看這些輸入代碼之前
Expression
Addop
Term
Mulop
Factor
這裡的文法可能和BNF范式有點不同
為了讓詞法分析做得更簡單
PARSER_BEGIN(Grammar)
public class Grammar implements NodeType {
public ParseTreeNode GetParseTree(InputStream in) throws ParseException
{
Grammar parser =new Grammar(in);
return parser
}
}
PARSER_END(Grammar)
SKIP :
{
}
TOKEN :
{
< ID: [
| < NUM: ( [
| < PLUS:
| < MINUS:
| < TIMERS:
| < OVER:
| < LPAREN:
| < RPAREN:
}
ParseTreeNode Expression() :
{
ParseTreeNode ParseTree = null;
ParseTreeNode node;
}
{
( node=Simple_Expression()
{
if(ParseTree == null)
ParseTree =node;
else
{
ParseTreeNode t;
t= ParseTree;
while(t
t=t
t
}
}
)*
{ return ParseTree;}
<EOF>
}
ParseTreeNode Simple_Expression() :
{
ParseTreeNode node;
ParseTreeNode t;
int op;
}
{
node=Term(){}
(
op=addop() t=Term()
{
ParseTreeNode newNode = new ParseTreeNode();
newNode
newNode
newNode
switch(op)
{
case PlusOP:
newNode
break;
case MinusOP:
newNode
break;
}
node = newNode;
}
)*
{ return node; }
}
int addop() : {}
{
<PLUS> { return PlusOP; }
| <MINUS> { return MinusOP; }
}
ParseTreeNode Term() :
{
ParseTreeNode node;
ParseTreeNode t;
int op;
}
{
node=Factor(){}
(
op=mulop() t=Factor()
{
ParseTreeNode newNode = new ParseTreeNode();
newNode
newNode
newNode
switch(op)
{
case TimersOP:
newNode
break;
case OverOP:
newNode
break;
}
node = newNode;
}
)*
{
return node;
}
}
int mulop() :{}
{
<TIMERS> { return TimersOP; }
| <OVER> { return OverOP; }
}
ParseTreeNode Factor() :
{
ParseTreeNode node;
Token t;
}
{
t=<ID>
{
node=new ParseTreeNode();
node
node
return node;
}
|
t=<NUM>
{
node=new ParseTreeNode();
node
node
node
return node;
}
|
<LPAREN> node=Simple_Expression() <RPAREN>
{
return node;
}
}
其中 SKIP 中的定義就是在進行詞法分析的同時
這個例子就有多個非終結符號
以 Simple_Expression() 過程為例
關於 Yacc 的使用
至於其它的文法操作解釋我就不再多說了
JavaCC 的下載地址是
From:http://tw.wingwit.com/Article/program/Java/JSP/201311/19412.html