概述
编号:
实习 | 一 | 二 | 三 | 四 | 五 | 六 | 七 | 八 | 九 | 十 | 总评 | 教师签名 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
成绩 |
第一部分 语言语法规则
Mini语言包含程序设计所需要的最基本语言成分,包括
-
程序定义语句 :以 program 开头 end 结尾,中间需要有 main()函数
-
赋值语句 :var 标识符 = 表达式;
-
算数表达式:包含 + - * / ()运算
-
逻辑表达式:包含 II && ! ()运算
-
if-else 语句:if (逻辑表达式或变量)begin 程序体 end else begin 程序体 end
-
while 循环语句:while(逻辑表达式或变量)begin 循环体 end
-
break 语句:break;
第二部分 文法定义
简化后的单词编码表为
单词符号 | 编码 | 单词符号 | 编码 |
---|---|---|---|
main | 1 | + | 15 |
if | 2 | - | 16 |
else | 3 | * | 17 |
while | 4 | / | 18 |
program | 5 | = | 19 |
begin | 6 | && | 20 |
end | 7 | || | 21 |
var | 8 | ! | 22 |
break | 9 | == | 23 |
true | 10 | 整数常量表 | 24 |
false | 11 | 浮点数常量表 | 25 |
( | 12 | 标识符表 | 26 |
) | 13 | ||
; | 14 |
先有词法分析器将程序扫描一遍,得到Token串,例如main转为<1,->,if转为<2,->...!转为<22,->,特别的标识符,整数常量,浮点数常量有两个表分别转换为<23,i>.<24,i>,<25,i>.
但是在语法分析的文法中,为了方便理解,这里依然用main等字符串,而不是使用<1,->进行分析,其中标识符用id表示,整数常量用wholenum表示,浮点数用floatnum表示。
得到如下的上下文无关文法G(S),(小写表示终结符号,大写表示非终结符号)
-
S ->PROGRAM //PROGRAM为整个语法程序
-
PROGRAM -> program PROBODY end
//PROBODY为程序体
-
PROBODY -> main begin PROSTATEMENT end
//PROSTATEMENT为程序语句
-
PROSTATEMENT -> ASSIGNMENT PROSTATEMENT | CONDITION PROSTATEMENT | LOOP PROSTATEMENT | BREAK PROSTATEMENT | ε //ASSIGNMENT为赋值语句 COUNT 为算数表达式 LOGIC 为逻辑表达式 CONDITION 为if else 分支语句 LOOP 为while循环语句 BREAK 为break语句,用于跳出循环//
-
ASSIGNMENT -> var id = VALUE ;
//VAlUE 为赋值语句可以赋的值,id为变量,属于词法分析器中单词编码表中的标识符
-
VALUE -> id | COUNT | LOGIC
-
COUNT -> TF F -> +T | -T | ε T -> GH H -> *G | /G | ε G -> (COUNT) | wholenum | floatunm | id
//wholenum 为词法分析器中单词编码表中的整数,floatnum为词法分析器中词法编码表中的浮点数,整个算术运算符表达,每个算数单元可以是数字也可以是变量
-
LOGIC -> IJ J -> ||I | ==I | ε I -> KL L -> &&K |ε K -> !M | M M -> (LOGIC) | true | false | id
//这里是逻辑表达式,每个逻辑单元可以是true false 也可以是变量
-
CONDITION -> if (LOGIC) begin PROSTATEMENT end ELSE
//ELSE是else语句
-
ELSE -> begin PROSTATEMENT end | ε
//if else语句中,先进行逻辑语句的判读,然后进入程序语句,else是可空的
-
LOOP -> while (LOGIC) begin PROSTATEMENT end
//循环语句
-
BREAK -> break ;
//break跳出语句
第三部分 语法分析算法
使用递归下降算法,结合词法分析器,用get_nexttoken();
函数表示取到下一个token串,用w.nexttoken();表示w后面的token串,用Token数据结构表示token串,所有的终结符号都使用Token进行定义,由于这些字符原本就是c语言的关键字,所以为了区分,将所有Mini文法中的关键字在程序表达中都加上s,边界符使用S+所对应的数字表示,如‘(’用S12表示。
Token mains = new Token(1);
Token ifs = new Token(1);
Token elses = new Token(1);
Token whiles = new Token(1);
.
.
.
Token S12 = new Token(12);
Token S13 = new Token(13);
Token S14 = new Token(14);
Token S15 = new Token(15);
.
.
.
Token id = new Token(26);
Token wholenum = new Token(24);
Token floatnum = new Token(25);
get_nexttoken(w);从词法分析器中取下一个token串,存放在全局变量w中
每个非终结符号都是一个函数,如下所示
void PROGRAM (){
if(w==programs)
{
get_nexttoken(w);
PROBODY();
if(w==end){
print("程序正确!");
}
else{
error(0);
}
}
else error(0);
}
void PROBODY (){
if(w==mains){
get_nexttoken(w);
if(w==begins){
get_nexttoken(w);
PROSTATEMENT();
if(w==ends){
get_nexttoken(w);
}
else error(1);
}
else error(1);
}
else error(1);
}
void PROSTATEMENT (){
if(w==vars) {
ASSIGNMEN();
PROSTATEMENT ();
}
else if(w==ifs) {
CONDITION();
PROSTATEMENT ();
}
else if(w==whiles) {
LOOP();
PROSTATEMENT ();
}
else if(w==breaks) {
BREAK();
PROSTATEMENT ();
}
else if(w==ends);
else error(2);
}
void ASSIGNMENT (){
if(w==var){
get_nexttoken(w);
if(w==id){
get_nexttoken(w);
if(w==S19){
get_nexttoken(w);
VALUE();
if(w==S14)
get_nexttoken(w);
else error(3);
}
else error(3);
}
else error(3);
}
else error(3);
}
void VALUE (){
if(w==wholenum) COUNT();
else if(w==floatnum) COUNT();
else if(w==trues) LOGIC();
else if(w==falses) gLOGIC();
else if(w==id&&w.nexttoken==S14) get_nexttoken(w);
else if (!(w==id&&w.nexttoken==S14)||w==S12||w==id){
if(w==S12&&w.nexttoken==id){
if(w.nexttoken.nexttoken==(S15||S16||S17||S18){
COUNT();
}
else if(w.nexttoken.nexttoken==(S20||S21||S23){
LOGIC();
}
else error(4);
}
else if(w==S12&&(w.nexttoken==(wholenum||floatnum))){
COUNT();
}
else if (w==S12&&(w.nexttoken==(true||false))){
LOGIC();
}
else if(w==id&&(w.nexttoken==(S15||S16||S17||S18)){
COUNT();
}
else if(w==id&&(w.nexttoken==S20||S21||S23)){
LOGIC();
}
else error(4);
}
else error(4);
}
void COUNT(){
T();
F();
}
void F(){
if(w==S15||w==S16){
get_nexttoken(w);
T();
}
}
void T(){
G();
H();
}
void H(){
if(w==S17||w==S18){
get_nettoken(w);
G();
}
}
void G(){
if(w==S12){
get_nexttoken(w);
COUNT();
if(w==S13){
get_nexttoken(w);
}
else error(5);
}
else if(w==(wholenum||floatnum||id)){
get_nexttoken(w);
}
else error(5);
}
void LOGIC(){
I();
J();
}
void J(){
if(w==(S21||23)){
get_nexttoken(w);
I();
}
}
void I(){
K();
L();
}
void L(){
if(w==S20)
{
get_nexttoken(w);
K();
}
}
void K(){
if(w==!){
get_nexttoken(w);
M();
}
else{
M();
}
}
void M(){
if(w==S11){
get_nexttoken(w);
LOGIC();
if(w==S12){
get_nexttoken(w);
}
else error(6);
}
else if(w==(trues||falses||id)){
get_nexttoken(w);
}
else error(6);
}
void CONDITION(){
if(w==ifs){
get_nexttoken(w);
if(w==S12){
get_nexttoken(w);
LOGIC();
if(w==S13){
get_nexttoken(w);
if(w==begins){
get_nexttoken(w);
PROSTATEMNT();
if(w==ends){
get_nexttoken(w);
ELSE();
}
else error(7);
}
else error(7);
}
else error(7);
}
else error(7);
}
else error(7);
}
void ELSE(){
if(w==begins){
get_nexttoken(w);
PROSTATEMENT();
if(w==ends){
get_nexttoken(w);
}
else{
error(7);
}
}
}
void LOOP(){
if(w==whiles&&(w.nexttoken==S12)){
get_nexttoken(w);
get_nexttoken(w);
LOGIC();
if(w==begins){
get_nexttoken(w);
PROSTATEMENT();
if(w==ends){
get_nexttoken(w);
}
else error(8);
}
else error(8);
}
else error(8);
}
void BREAK(){
if(w==breaks&&(w.nexttoken==S14)){
get_nexttoken(w);
get_nexttoken(w);
}
else{
error(9);
}
}
第四部分 出错处理出口
程序出错时,其实w记录了出错所在的token串,只需用另一个变量记录token串所在整个程序的位置,在使用get_nettoken()
取到下一个token串时,变量加一,就可以判断程序出错的位置。
错误函数 | 错误产生式 | 错误类型 |
---|---|---|
error(0) | PROGRAM -> program PROBODY end | 程序定义错误 |
error(1) | PROBODY -> main begin PROSTATEMENT end | 程序体定义错误 |
error(2) | PROSTATEMENT -> ASSIGNMENT | CONDITION | LOOP | BREAK | ε | 语句定义不合法 |
error(3) | ASSIGNMENT -> var id = VALUE ; | 赋值语句格式错误 |
error(4) | VALUE -> id | COUNT | LOGIC | 赋值语句右值不正确 |
error(5) | G -> (COUNT) | wholenum | floatunm | id | 算数表达式格式错误 |
error(6) | M -> (LOGIC) | true | false | id | 逻辑表达式格式错误 |
error(7) | CONDITION -> if (LOGIC) begin PROSTATEMENT end ELSE | 条件语句错误 |
error(8) | LOOP -> while (LOGIC) begin PROSTATEMENT end | 循环语句错误 |
error(9) | BREAK -> break ; | 跳出语句错误 |
第五部分 测试计划
测试用例中所包括的语法单位应该尽可能覆盖Mini语言的文法中的所有非终结符,包括程序定义、变量声明、if-else语句、赋值语句、条件语句、循环语句、跳出语句、算数表达式和逻辑表达式。
测试用例如下
program
main begin
var logic=true;
var i=0;
while(i<10)
begin
if(logic&&(!(!true)))
begin
i=i+1;
logic=!logic;
end
else
begin
logic=!logic;
end
end
end
end
测试结果,无错误!
最后
以上就是幽默大米为你收集整理的编译原理语法分析器实验报告的全部内容,希望文章能够帮你解决编译原理语法分析器实验报告所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复