JavaCC==语法分析==实验二
JavaCC 语法分析实验二
一、实验目的:
- 掌握 JavaCC 语法分析器工作原理;
- 设计 MiniC 的上下文无关文法,在“Parser.jjt”文件中表示该文法,生
成调试递归下降分析程序,以便对任意输入的符号串进行分析; - 输出语法树。
二、MiniC 语法
〈程序〉 → int main() {〈语句块〉* }
〈语句块〉 →〈语句〉| {〈语句块〉* }
〈语句〉 →〈顺序语句〉|〈条件语句〉|〈循环语句〉
〈顺序语句〉→ (〈声明语句〉| 〈赋值语句〉) ”;” 〈声明语句〉→ int ID,ID,…,ID //思考如何表示
〈赋值语句〉→ ID =〈表达式〉
〈条件语句〉→ if (〈条件〉)〈语句块〉 else 〈语句块〉
〈循环语句〉→ while (〈条件〉)〈语句块〉
〈条件〉 →〈表达式〉〈关系符〉〈表达式〉
〈表达式〉 → // 可以使用javacc自动生成的 表达式(Expression)的文法
〈关系符〉 → <| <=| >| >= | ==| !=
注意:该文法为参考文法,可以对其适当修改。首先,文件中的文法必须
不含左递归和回溯;其次,同学们可以补充其它语法规则,如布尔表达式,for
语句等。
三、实习要求
- 以文件流的形式读入要分析的 C 语言程序;
- 如果输入的源程序符合 MiniC 的语法规范,输出语法树。
扩展要求:具有错误检查的能力,可以输出错误所在的行号,并简单提
示。
四、实验过程和指导:
-
新建一个用于 javacc 编辑的 jjt 模板文件:
(1)新建 java 项目
(2)建立一个语法分析包(例如:package parser)
(3)在 parser 包内,“新建”-“其它”-“JavaCC Template File”
(4)创建一个“.jjt”文件,如图 1 所示,建议选用“Non staitc”模式:
-
在模板文件中修改词法部分和语法部分(如图 2 所示),将 MiniC 的文法依照要求写入 jjt 文件。
-
修改 jjt 文件的 main 方法(如图 2 所示),使其执行任务是:指定要进
行语法分析的源程序,执行语法分析,输出语法树。
五、程序输入/输出示例:
要求:测试多组源程序查看结果。
图 3 和图 4 为一组作为参考的测试源代码及其对应的语法树,具体的语法
树节点来自于同学们自定义的文法。
注意:文法的定义不同,语法树的层级关系则不同。
六.实验jjt源代码:
1.Start部分
impleNode Start() :
{}
{
Program()
{
return jjtThis;
}
}
void Program() :
{}
{
< INT>
< MAIN>
< LBRACE>
< RBRACE>
< BLBRACE>
(SentenceBlock())*
(
ReturnSent()
)
< BRBRACE>
}
void SentenceBlock():
{}
{
Sentence()
| < BLBRACE>
(SentenceBlock())*
< BRBRACE>
}
void Sentence() :
{}
{
SequenceSen()
| ConditionSen()
| LoopSent()
}
void SequenceSen() :
{}
{
[
AssigmentSen()
| DeclareSen()
]
< SEMICOLON>
}
void DeclareSen() :
{}
{
[
<INT>
| <DOUBLE>
| <FLOAT>
| <CHAR>
]
Identifier()
(<COMMA> Identifier())*
}
void AssigmentSen() :
{}
{
Identifier()
<ASSIGN>
Expression()
}
void ConditionSen() :
{}
{
<IF>
Condition()
SentenceBlock()
}
void LoopSent() :
{}
{
<WHILE>
Condition()
SentenceBlock()
}
void Condition() :
{}
{
"("
Expression()
Relations()
Expression()
")"
}
void Expression() :
{}
{
AdditiveExpression()
}
void AdditiveExpression() :
{}
{
MultiplicativeExpression()
(
(
"+"
| "-"
)
MultiplicativeExpression()
)*
}
void MultiplicativeExpression() :
{}
{
UnaryExpression()
(
(
"*"
| "/"
| "%"
)
UnaryExpression()
)*
}
void UnaryExpression() :
{}
{
"(" Expression() ")"
| Identifier()
| Integer()
}
void Identifier() :
{}
{
< IDENTIFIER >
}
void Integer() :
{}
{
< INTEGER_LITERAL >
}
void Relations() :
{}
{
<GT>
| <LT>
| <EQUAL>
}
void ReturnSent() :
{}
{
< RETURN > <INTEGER_LITERAL> < SEMICOLON>
}
2.main方法部分
import java.io.FileReader;
import java.io.FileNotFoundException;
public class WorkGrammar
{
public static void main(String args [])throws FileNotFoundException
{
System.out.println("语法分析");
FileReader Fr = new FileReader("test3.txt");
new WorkGrammar(Fr);
try
{
SimpleNode n = WorkGrammar.Start();
n.dump("");
System.out.println("END");
}
catch (Exception e)
{
System.out.println("Oops.");
System.out.println(e.getMessage());
}
}
}
3.源jjt代码
/**
* JJTree template file created by SF JavaCC plugin 1.5.28+ wizard for JavaCC 1.5.0+
*/
options
{
static = true;
}
PARSER_BEGIN(WorkGrammar)
package WorkGrammar;
import java.io.FileReader;
import java.io.FileNotFoundException;
public class WorkGrammar
{
public static void main(String args [])throws FileNotFoundException
{
System.out.println("语法分析");
FileReader Fr = new FileReader("test.txt");
new WorkGrammar(Fr);
try
{
SimpleNode n = WorkGrammar.Start();
n.dump("");
System.out.println("END");
}
catch (Exception e)
{
System.out.println("Oops.");
System.out.println(e.getMessage());
}
}
}
PARSER_END(WorkGrammar)
SKIP :
{
" "
| "\t"
| "\n"
| "\r"
| < "//" (~[ "\n", "\r" ])*
(
"\n"
| "\r"
| "\r\n"
) >
| < "/*" (~[ "*" ])* "*"
(
~[ "/" ] (~[ "*" ])* "*"
)*
"/" >
}
TOKEN : /* KEYS */
{
< INT : "int" >
| < DOUBLE : "double" >
| < FLOAT : "float" >
| < CHAR : "char" >
| < VOID : "void" >
| < FOR : "for" >
| < WHILE : "while" >
| < RETURN : "return" >
| < IF : "if" >
| < MAIN:"main">
}
TOKEN : /* LITERALS */
{
< INTEGER_LITERAL :
< DECIMAL_LITERAL > ([ "l", "L" ])?
| < HEX_LITERAL > ([ "l", "L" ])?
| < OCTAL_LITERAL > ([ "l", "L" ])?
>
| < #DECIMAL_LITERAL : [ "1"-"9" ] ([ "0"-"9" ])* >
| < #HEX_LITERAL : "0" [ "x", "X" ] ([ "0"-"9", "a"-"f", "A"-"F" ])+ >
| < #OCTAL_LITERAL : "0" ([ "0"-"7" ])* >
}
TOKEN : /* OPERATORS */
{
< PLUS : "+" >
| < MINUS : "-" >
| < MULTIPLY : "*" >
| < DIVIDE : "/" >
| < ASSIGN : "=" >
| < GT : ">" >
| < LT : "<" >
| < EQUAL : "==" >
}
TOKEN : /* SEPARATER */
{
< QUATION : "\"" >
| < SEMICOLON : ";" >
| < BLBRACE : "{" >
| < BRBRACE : "}" >
| < LBRACE : "(" >
| < RBRACE : ")" >
| < COMMA : "," >
| < EXCLA_SYM : "!" >
}
TOKEN : /* IDENTIFIERS */
{
< IDENTIFIER :
< LETTER >
(
< LETTER >
| < DIGIT >
)* >
| < #LETTER : [ "_", "a"-"z", "A"-"Z" ] >
| < #DIGIT : [ "0"-"9" ] >
}
SimpleNode Start() :
{}
{
Program()
{
return jjtThis;
}
}
void Program() :
{}
{
< INT>
< MAIN>
< LBRACE>
< RBRACE>
< BLBRACE>
(SentenceBlock())*
(
ReturnSent()
)
< BRBRACE>
}
void SentenceBlock():
{}
{
Sentence()
| < BLBRACE>
(SentenceBlock())*
< BRBRACE>
}
void Sentence() :
{}
{
SequenceSen()
| ConditionSen()
| LoopSent()
}
void SequenceSen() :
{}
{
[
AssigmentSen()
| DeclareSen()
]
< SEMICOLON>
}
void DeclareSen() :
{}
{
[
<INT>
| <DOUBLE>
| <FLOAT>
| <CHAR>
]
Identifier()
(<COMMA> Identifier())*
}
void AssigmentSen() :
{}
{
Identifier()
<ASSIGN>
Expression()
}
void ConditionSen() :
{}
{
<IF>
Condition()
SentenceBlock()
}
void LoopSent() :
{}
{
<WHILE>
Condition()
SentenceBlock()
}
void Condition() :
{}
{
"("
Expression()
Relations()
Expression()
")"
}
void Expression() :
{}
{
AdditiveExpression()
}
void AdditiveExpression() :
{}
{
MultiplicativeExpression()
(
(
"+"
| "-"
)
MultiplicativeExpression()
)*
}
void MultiplicativeExpression() :
{}
{
UnaryExpression()
(
(
"*"
| "/"
| "%"
)
UnaryExpression()
)*
}
void UnaryExpression() :
{}
{
"(" Expression() ")"
| Identifier()
| Integer()
}
void Identifier() :
{}
{
< IDENTIFIER >
}
void Integer() :
{}
{
< INTEGER_LITERAL >
}
void Relations() :
{}
{
<GT>
| <LT>
| <EQUAL>
}
void ReturnSent() :
{}
{
< RETURN > <INTEGER_LITERAL> < SEMICOLON>
}
七.实验结果
//实验测试一
int main(){
int a,b;
a = 23;
while(a>2){
int x;
x = a+b;
}
return 0;
}
//实验测试二
int main(){
int a,b;
a=1;
b=3;
if(a<b){
int x;
x = a;
a = b;
b = x;
}
return 0;
}