📄 编译器.cpp
字号:
if(sym=="rparen") //子表达式分析完后,应遇到右括号
{
getsym();
}
else
error(22);
}//if
test(fsys,facbegsys,23); //一个因子处理完毕,遇到的token应在fsys集合中
//如果不是,抛23号错,并找到下一个因子的开始,使语法分析可以继续运行下去
}//while
}//factor
void term(symset fsys){ //项处理
string mulop;
//factor([times,slash]+fsys); //每一个项都应该由因子开始,因此调用factor子程序分析因子
addsym(fsys,"times");
addsym(fsys,"slash");
if (sym=="times"||sym=="slash"){ //一个因子后应当遇到乘号或除号
mulop=sym;
getsym();
//factor(fsys+[times,slash]); //调factor子程序分析因子
addsym(fsys,"times");
addsym(fsys,"slash");
if (mulop=="times"){ //如果刚才遇到乘号
gen("opr",0,4); //生成乘法指令
}
else
gen("opr",0,5); //生成除法指令
}//if
}//term
void condition(symset fsys){ //条件处理过程condition
string relop; //用于临时记录token(这里一定是一个二元逻辑运算符)的内容
string a[6]={"eql","neq","lss","leq","gtr","geq"};
int k=0;
int j=0;
if(sym=="oddsym") //如果是odd运算符(一元
{
getsym();
expression(fsys);
gen("opr",0,6); //生成6号操作指令:奇偶判断运算
}
else
{
//expression([eql,neq,lss,leq,gtr,geq]+fsys); //对表达式左部进行处理计算
addsym(fsys,"eql");
addsym(fsys,"neq");
addsym(fsys,"lss");
addsym(fsys,"leq");
addsym(fsys,"gtr");
addsym(fsys,"qep");
expression(fsys);
for(int i=0;i<6;i++)
{
if(sym==a[i])
k=1;
else k=-1;
}
if(k==1){
relop=sym;
getsym();
expression(fsys); //对表达式右部进行处理计算
if (relop=="eql")
j=1;
else if(relop=="neq")
j=2;
else if(relop=="lss")
j=3;
else if(relop=="geq")
j=4;
else if(relop=="gtr")
j=5;
else if(relop=="leq")
j=6;
switch(j){
case 1: {
gen("opr",0,8); //等号:产生8号判等指令
break;
}
case 2: {
gen("opr",0,9); //不等号:产生9号判不等指令
break;
}
case 3: {
gen("opr",0,10); //小于号:产生10号判小指令
break;
}
case 4: {
gen("opr",0,11); //大于等号号:产生11号判不小于指令
break;
}
case 5: {
gen("opr",0,12); //大于号:产生12号判大于指令
break;
}
case 6: {
gen("opr",0,13); //小于等于号:产生13号判不大于指令
break;
}
}//switch
}//if
if(k==-1)
error(20);
}
}//condition
void statement(){ //语句处理过程
int i,cx1,cx2;
int psw=0; //标志位
if (sym=="ident")
psw=1; //如果以标识符开头,psw为1
if (sym=="readsym")
psw=2; //如果是read语句
if (sym=="writesym")
psw=3; //如果遇到write语句
if (sym=="callsym")
psw=4; //如果遇到call语句
if (sym=="ifsym")
psw=5; //如果遇到if语句
if (sym=="beginsym")
psw=6; //如果遇到begin语句
if (sym=="whilesym")
psw=7; //如果遇到while语句
switch(psw)
{
case 1: {
i=position(id); //在符号表里查找该标识符的位置
if (i==0)
{ error(11);}
else if (table[i].kind!="variable") //若找到 但该标识符不是变量名
{
error(12);
i=0;
}
getsym(); //获得下一个token,正常应为赋值号
if (sym=="becomes")
getsym(); //如果的确为赋值号,获取下一个token,正常应为一个表达式
else
error(13);
expression(fsys); //处理表达式
if (i!=0)
{
gen("sto",lev-table[i].level,table[i].adr);
}
break;
}
case 2: {
getsym(); //获得下一token,正常情况下应为左括号
if (sym!="lparen") //如果read语句后跟的不是左括号
error(34);
else
while(sym!="comma") //右括号为止
{
getsym();
if (sym=="ident")
i=position(id);
else
i=0;
if(i==0)
error(35);
else
{
//with
gen("opr",0,16);
gen("sto",lev-table[i].level,table[i].adr);
}
getsym();
}
if (sym!="rparen") //如果不是右括号
{
error(33);
while(insym(sym,fsys)) //依靠fsys集,找到下一个合法的token,恢复语法分析
{
getsym();
}
}
else getsym(); //如果read语句正常结束,得到下一个token,一般为分号或end
break;
}
case 3: {
getsym(); //获取下一token,正常应为左括号
if (sym=="lparen")
{
while (sym!="comma")
{
getsym();
addsym(fsys,"rparen");
addsym(fsys,"comma");
expression(fsys); //调用expression过程分析表达式,用于出错恢复的集合中加上右括号和逗号
gen("opr",0,14); //生成14号指令:向屏幕输出
}
if(sym!="rparen")
error(35);
else getsym(); //正常情况下要获取下一个token,为后面准备好
}
gen("opr",0,15); //生成一个15号指令,功能是输出一个换行
break;
}
case 4: {
getsym(); //获取token,应是过程名型标识符
if(sym!="ident")
error(14);
else
i=position(id);
if(i==0)
error(11);
else
{
//while()
{
if (table[i].kind=="procedur") //如果这个标识符为一个过程名
gen("cal",lev-table[i].level,table[i].adr); //生成cal目标代码,呼叫这个过程
else error(15);
}
getsym();
}
break;
}
case 5: {
getsym(); //获取一token应是一个逻辑表达式
addsym(fsys,"thensym");
addsym(fsys,"dosym");
condition(fsys);
if(sym=="then")
getsym();
else
error(16);
cx1=cx; //记下当前代码分配指针位置
gen("jpc",0,0); //生成条件跳转指令,跳转位置暂时填0,分析完语句后再填写
statement(); //分析then后的语句
code[cx1].a=cx; //上一行指令(cx1所指的)的跳转位置应为当前cx所指位置
break;
}
case 6: {
getsym();
addsym(fsys,"semicolon");
addsym(fsys,"endsym");
statement(); //对begin与end之间的语句进行分析处理
while((sym=="semicolon")||(sym=="statbegsys")) //如果分析完一句后遇到分号或语句开始符循环分析下一句语句
{
if(sym=="semicolon") //如果语句是分号(可能是空语句)
getsym();
else
error(10); //如果语句与语句间没有分号,出10号错
addsym(fsys,"semicolon");
addsym(fsys,"endsym");
statement();
}
if(sym=="endsym") //如果语句全分析完了,应该遇到end
getsym();
else error(17);
break;
}
case 7: {
cx1=cx; //记下当前代码分配位置,这是while循环的开始位置
getsym();
addsym(fsys,"dosym");
condition(fsys); //对这个逻辑表达式进行分析计算
cx2=cx; //记下当前代码分配位置,这是while的do中的语句的开始位置
gen("jpc",0,0); //生成条件跳转指令,跳转位置暂时填0
if(sym=="dosym") //逻辑表达式后应为do语句
getsym();
else error(18);
statement(); //分析do后的语句块
gen("jmp",0,cx1); //循环跳转到cx1位置,即再次进行逻辑判断
code[cx2].a=cx; //把刚才填0的跳转位置改成当前位置,完成while语句的处理
break;
}
}
//test(fsys, [ ], 19) //
}
////////////////////////////////////////////////////////////////////////////
void constdeclaration() { //常量声明处理过程
if (sym=="ident") {
getsym();
if (sym=="becomes"||sym=="eql") {
if (sym=="becomes") { //如果是赋值号(常量生明中应该是等号)
error(1);
}
getsym();
if (sym=="number") {
enter("constant"); //把这个常量登陆到符号表
getsym();
}
else {
error(2); //如果等号后接的不是数字,抛出2号错误
}
}
else {
error(3); //如果常量标识符后接的不是等号或赋值号,抛出3号错误
}
}
else {
error(4); //如果常量声明过程遇到的第一个符号不为标识符,抛出4号错误
}
}
void vardeclaration() { //变量声明过程
if (sym=="ident") {
enter("variable");
getsym();
}
else { //如果变量声明过程遇到的第一个符号不是标识符,抛出4号错误
error(4);
}
}
void block(int lev,int tx,string fsys) { //语法分析
dx=3; //地址指示器给出每层局部量当前已分配到的相对位置
tx0=tx; //初始符号表指针指向当前层的符号在符号表中的开始位置
gen("jmp",0,0); //产生一行跳转指令,跳转位置暂时未知填0
if (lev>levmax) { //如果当前过程嵌套层数大于最大允许的套层数
error(32);
}
while (sym=="constsym"||sym=="varsym"||sym=="procsym") { //常量说明,变量说明,过程说明
if (sym=="constsym") { //常量说明处理
getsym();
while (sym=="ident") {
constdeclaration();
while (sym=="comma") { //如果遇到了逗号则反复声明下一个常量
getsym();
constdeclaration();
}
if (sym=="semicolon") { //如果常量声明结束,应遇到分号
getsym();
}
else {
error(5); //如果常量声明语句结束后没有遇到分号则发出5号错误
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -