javacc编译原理实训报告

一、综合训练目的与要求
本综合训练是软件工程专业重要的实践性环节之一,是在学生学习完《编译原理》课程后进行的综合练习。
本课综合训练的目的:

  1. 巩固和加深学生对编译原理课程基本知识的理解和掌握;
  2. 提高抽象思维能力以及加深理解编译系统的原理;
  3. 掌握利用JavaCC开发编译系统的方法;
  4. 掌握书写设计与实现编译系统说明文档的能力;
  5. 提高综合运用算法、程序设计语言、数据结构知识的能力。
    本课程综合训练的要求:
    1.使用文件读入的方式测试编译程序;
    2.将词法分析、语法分析和语义分析结果分别以文件方式输出;
    3.尽可能实现要求的功能,可以自己决定实现哪些扩展功能;
    4.不要求实现界面,重点实现编译功能。(开发时间有剩余的同学可以实现界面。)
    编译功能要求:
    1.能够根据单词的构词规则,完成MiniC语言中的单词的解析(词法分析),如果不符合单词的构词规则,请给出错误信息。如果源语言符合单词的词法规则,输出<单词种别,单词自身值>二元式;
    2.在词法分析的基础上,构造MiniC的递归下降分析文法,利用JavaCC实现递归下降文法。判断源语言是否符合MiniC的语法,如果符合,输出语法树;否则,请给出语法错误信息;
    3.在语法分析的基础上,根据属性文法制导翻译,进行语义分析,输出四元式。如果源语言不符合MiniC的语义,请指出错误信息;
    4.在实习课的基础上,整个编译系统要能够翻译声明语句、赋值语句、布尔表达式,if-else, for, while,do-while,switch-case等语句嵌套的分析与翻译;符号表、语义错误检查:变量重复声明、变量使用时未定义。
    5.扩展内容:可以考虑自增、自减、main()方法调用其它子程序的翻译、数组(二维,多维)翻译、数组下标越界等错误、变量赋值精度错误、函数返回值类型不匹配等;
    6.扩展内容:可以添加功能,如break、continue、return语句、一维指针等。
    二、综合训练任务描述
    首先需要的是大概的确立大致的结构,我们可以使用之前实验所给的MiniC语法,并且对上诉的编译功能要求做出响应的修改和添加;
    1.实现功能的顺序可以按着学习和实验的顺序来进行,我们可以先进行词法分析部分的代码编写,添加相应的所需要的词法规则,用代码来描述对象语言的词法规则,将关键字、标识符、分隔符、运算符、常数和其他需要过滤掉的字符;定义完成后对mian函数进行添加修改,使用文件输出流、输入流来对测试代码文件进行读出处理后再将词法分析输出的值和对应的关键字输出到指定的文件中。
    在这里插入图片描述

图 1 词法分析
2.在完成了对词法分析的操作后我们进一步的来完善我们的语法,语法方面我们可以对之前实验用到的MiniC语法进行修改添加成我们自己的语法,如下:
<程序> ->Type main(){<语句块>}
<语句块> -><语句>|{<语句块>
}
<顺序语句> ->(<声明语句>|<赋值语句>)”;”
<声明语句> ->Type ID,ID,…,ID
<赋值语句> ->ID =<表达式>
<条件语句> ->if(<booler表达式>)<语句块>else<语句块>
<循环语句> ->while(<booler表达式>)<语句块>
<for循环语句>->FOR(AssignSentence”;”<booler表达式>”;”AssignSentence){语句块}
<do-while语句>->do(语句块)while( <逻辑>)”;”
<switch-case语句>->switch){(case <INTEGER_LITERAL>”:”(语句块)* break”;”)* [defaults:[语句块]break”;”]}
<booler表达式>-><表达式>(<关系符><表达式>)?((|()))?
<逻辑> -><条件>(<逻辑运算符><条件>)*
<条件> -><表达式>(<关系符><表达式>)?
<表达式> ->//对默认的进行小小的修改
<关系符> -><|<=|>|>=|==|!=
<逻辑运算> ->&& | || (包含在逻辑中)
语法部分根据了进度的变化做了相对的调整,这里就只展示最后修改的。
3.语法分析结束后开始对语义分析的代码编写,创建四元式并且对其进行拉链回填操作。
使用了老师所给的工具代码包来对功能进行实现。下面就将功能要求中的几个主要的功能进行代码的展示和运行结果的截图;
三、编译系统设计
在这里插入图片描述
在这里插入图片描述

图 2 编译类与辅助类图关系
多个辅助类,都放在了utils包中,并且几个类中都有联系,而且我们可以在我们的语法类中进行使用。
布尔表达式的代码如下:
ConditionValue Booler()😕/布尔表达式
//因为此处需要对所得的表达式需要拉链,但是要像通过Condition获取Value的话就不能获取QTInfo的对象
{
ConditionValue Value = new ConditionValue();
String str1 = null,str2 = null;
Token op = null;
Token op1= null;
ConditionValue Value2 = new ConditionValue();
ConditionValue Valuet = new ConditionValue();
int qtSize = QTInfo.size;
QTInfo qt1;
QTInfo qt2;

}
{

str1 = Expression()
(op=Relations() str2 = Expression())?
{
// QTInfo qt1;
if(op != null) {
qt1 = new QTInfo(“J”+op.image,str1,str2,QTInfo.size+3);
qtList.addQTInfo(qt1);
//Value.mergeTrue(qt1);
}
else {
qt1 = new QTInfo(“Jnz”,str1,““,QTInfo.size+3);
qtList.addQTInfo(qt1);
//Value.mergeTrue(qt1);
}
qt2 = new QTInfo(“J”,”
”,“_”,“F”);
qtList.addQTInfo(qt2);

Value.mergeFalse(qt2);
//Value.mergeFalse(qt2);
//Value.backpatchFalseChain(QTInfo.size+1);

}
(
(
op1=< AND >
{//回填?
Valuet = new ConditionValue();
Valuet.mergeFalse(qt2);
//Value.backpatchFalseChain(QTInfo.size+1);
//且出了问题,应该改为且的前后拉假链再重新定义假链

Value.backpatchTrueChain(QTInfo.size+1);
}
| (
op1=< OR >
{//回填?

//Value.mergeTrue(qt1);
Valuet.mergeFalse(qt2);
Valuet.backpatchFalseChain(QTInfo.size+1);
Value.backpatchFalseChain(QTInfo.size+1);
//Value.backpatchTrueChain(QTInfo.size+1);
}
)
)

Value2=Booler()
//只要跑到了这就是开始循环嵌套了,下面的语句是结束的时候跑的
{
if(op1.image.equals(“&&”))
{
//拉链回填?
// Value.mergeFalse(qt2);
// Value.mergeFalse(qt2);
// Value.backpatchFalseChain(QTInfo.size+1);
// Value = new ConditionValue();
Value2.mergeFalse(qt2);

   //且不在的第一位的时候可以用,但是第一位时不能直接拉
   Value2.backpatchFalseChain(QTInfo.size+1);
  
  }if(op1.image.equals("||"))
  {
     //拉链回填?

// Valuet.mergeFalse(qt2);
// Valuet.backpatchFalseChain(QTInfo.size+1);
Value2.mergeTrue(qt1);
Value2.backpatchTrueChain(QTInfo.size+1);
}
return Value2;
}
)?
{
return Value;
}
}
If-else语句,每次遇到If都回产生两个四元式,一个是条件为T时一个是条件为F,将T的拉真链,加的拉假链,然后在if中使用条件语句后将此时的QTInfo的数量回填两条链,有else的情况下再添加两个四元式,进行相似的操作。
If-else语句
在这里插入图片描述

图 3 if-else语句
While语句,就是使用了Booler表达式作为判断式,随后再将真链回填,再新建假链并且回填假链。
在这里插入图片描述

图 4 While循环语句
Switch-case语句,在每次的case中都回创建两条,一条是当当前的值匹配的话就跳到语句块,并且进行拉链回填上一个的假链,再重置这跳链以免拉链回填时回将前面的也一起填了从而导致覆盖问题。也就是每一个case的假链是连在了下一个假链的开始的。另一条是不匹配时跳到下一个case,并且进行拉链回填;之后再对defaults进行定义,直接添加default中的语句块所产生的四元式。

在这里插入图片描述
在这里插入图片描述

图 5 Switch-case语句
do-while语句,dowhile其实也就是类似于while。只需要对进行一些简单的修改便可,在判断条件正确的情况下返回到do,也就是拉链回填的一些逻辑的变化。
在这里插入图片描述

图 6 Do-While循环语句

添加符号表、语义错误检查:变量重复声明、变量使用时未定义:
符号表等相关工具代码老师都有给,添加到我们所使用的工具包中就可以,错误检查可以添加到相关操作的代码函数中。
在这里插入图片描述

图 7 变量重复声明
在这里插入图片描述

图 8赋值时未定义
在这里插入图片描述

图 9 变量使用时未定义
以上这些都能够实现语句的嵌套的分析和翻译。

四、调试与测试
在这里插入图片描述

图 10if-else
在这里插入图片描述

图 11While
在这里插入图片描述

图 12Switch-case
在这里插入图片描述

图 13 do-while
在这里插入图片描述
在这里插入图片描述

图 14 未定义错误检查
在这里插入图片描述

图 15 重复定义错误检查
五、实习日志
2021年12月27日 星期一
上午:合并之前的项目,将基本功能实现,写出for循环的语法分析
下午:对合并的项目的代码逻辑进行优化,并且写一部分for循环的语义分析
2021年12月28日 星期二
上午:将for循环的语义分析完成,并且完成do-while循环语句
下午:完成switch-case语法规则和语义分析
2021年12月29日 星期三
上午:添加布尔表达式的语法规则,并思考如何编写布尔表达式的语义分析
下午:完成布尔表达式的语义分析。
2021年12月30日 星期四
上午:添加错误分析
下午:写报告和ppt
2021年12月31日 星期五
上午:答辩
下午;写报告

六、实习总结
实现了基础的功能,也添加了几个额外操作,例如break和return,没有实现太多的额外功能。通过这次为时一周的编译原理实训,实现了一个MiniC语言编译系统的设计与实现,大部分的时间都花在了思考如何去实现语法分析的逻辑和语义分析的逻辑,拉链和回填代码的逻辑。通过对这个编译系统的编写实现,让我对如何去分析程序、词法语法规则以及编写四元式有了更加清晰的理解,逻辑更加清晰。

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
java编程 含有界面 以及完整代码 〈程序〉→ main()〈语句块〉 〈语句块〉→{〈语句串〉} 〈语句串〉→〈语句〉;〈语句串〉|〈语句〉; 〈语句〉→〈赋值语句〉|〈条件语句〉|〈循环语句〉 〈赋值语句〉→ ID =〈表达式〉; 〈条件语句〉→ if〈条件〉〈语句块〉 〈循环语句〉→ while〈条件〉〈语句块〉 〈条件〉→(〈表达式〉〈关系符〉〈表达式〉) 〈表达式〉→〈表达式〉〈运算符〉〈表达式〉|(〈表达式〉)|ID|NUM 〈运算符〉→+|-|*|/ 〈关系符〉→<|<=|>|>=|=|!> word.wordList包(存储了关键字): word:此类是定义了存储关键字的结构:包括String型的关键字,和int型的识别符。 wordList:此类存储了29个关键字,在构造函数中初始化。 2、word包(进行词法分析)中: basicFunction:此类定义了做词法分析的基本函数: GetChar()将下一输入字符读到ch中,搜索知识器前移一个字符位置 GetBC();检查ch中的字符是否为空白。若是,则调用GetChar直至不 是字符为止 Concat();将ch中的字符连接到strToken之后 IsLetter();判断ch中的字符是否为字母 IsDigit();判断ch中的字符是否为数字 Reserve();对strToken中的字符创查找保留字表,若是则返回它的编码,否则返回0 Retract();将搜索指示器回调一个字符位置 RetractStr();将strToken置空 lexAnalysis:此类是用来进行词法分析,将分析后的单词存入word数组中,(注:在词法分析中,若是一串字母,则认为是ID,若是数字,则认为是NUM。存储的时候识别符分别存ID与NUM的识别符,但是内容仍然是自己的内容) 其中的wordAnalysis函数就是词法分析函数(具体现请看后面的重要函数分析) 3、stack包(定义栈)中: 栈是通过链表来定义的,因此 StringListElement:次类定义了链表的每一个节点 StringStrack:此类定义了栈,其中有长度属性,有函数: Top();用来取得栈顶 Push();压栈 Pop();出栈 4、sentence包(语法分析)中: juzi :定义了文法的句子的结构:key(左边部分) content[](右边推出的部分) lo(长度) grammar :存储了文法的27个关系式 AnalysisFB :定义了分析表的存储结构 AnalysisF :存储分析表 SentenceAnalysis :语法分析 JuProduction(word w):此函数是用来判断在当前栈与输入串的情况下,用哪一个产生式,返回产生式在数组中的下标 若输入串的第一个字符与栈顶字符相同则表示可以规约,则返回-1; 若不能过用产生式,则返回-2; AnalysisBasic(word w):此函数是分布进行语法分析,对栈操作 * 根据所需要的产生式对符号栈进行操作 * 返回0表示规约;返回1表示移进;否则表示输入串不是文法的句子 5.Main包(主界面)中 Main:此类定义了图形界面

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值