【编译原理】根据给定文法,用C/C++语言编写Translation Schema,执行程序并给出结果
任务描述
本关任务:根据给定文法,用C/C++语言编写Translation Schema,执行程序并给出结果
相关知识
为了完成本关任务,你需要掌握:
- Translation Schema相关方法理论
- C/C++ 编程语言基础
- C语言的基本结构知识
Translation Schema
在动手设计之前,你应该先做好Translation Schema的相关准备工作。
你应该在你的程序中进行类型检查,以便对算术表达式(无论是整数算术还是实数算术)执行正确的操作。
C/C++
本实训涉及函数、结构体,标准流输入输出,字符串等操作
实验要求
实验文法定义
program -> decls compoundstmt
decls -> decl ; decls | E
decl -> int ID = INTNUM | real ID = REALNUM
stmt -> ifstmt | assgstmt | compoundstmt
compoundstmt -> { stmts }
stmts -> stmt stmts | E
ifstmt -> if ( boolexpr ) then stmt else stmt
assgstmt -> ID = arithexpr ;
boolexpr -> arithexpr boolop arithexpr
boolop -> < | > | <= | >= | ==
arithexpr -> multexpr arithexprprime
arithexprprime -> + multexpr arithexprprime | - multexpr arithexprprime | E
multexpr -> simpleexpr multexprprime
multexprprime -> * simpleexpr multexprprime | / simpleexpr multexprprime | E
simpleexpr -> ID | INTNUM | REALNUM | ( arithexpr )
起始符
program
保留字
{ }
if ( ) then else
ID =
> < >= <= ==
+ -
* /
ID INTNUM REALNUM
int ID =
real ID =
;
E 是'空'
ID为标识符,均以小写字母表示,例如:a,b,c.....
INTNUM是正整数
REALNUM是一个正实数(即INTNUM . INTNUM)
分隔方式
同一行的输入字符之间用一个空格字符分隔,例如:int a = 1 ; int b = 2 ;
错误处理
本实验需要考虑错误处理,如果程序不正确,它应该输出语义错误信息(与行号一起)并退出,不需要进行错误改正。 例如:
error message:line 1,realnum can not be translated into int type
输入
要求:在同一行中每个输入字符之间用一个空格字符分隔,无其余无关符号,输入输出全部为英文状态下字符。
样例输入:
int a = 1 ; int b = 2 ; real c = 3.0 ;
{
a = a + 1 ;
b = b * a ;
if ( a < b ) then c = c / 2 ; else c = c / 4 ;
}
输出
a: 2
b: 4
c: 1.5
输出变量名及其数值,中间相隔一个空格
按照正常步骤进行语法分析太麻烦了,打个表吧(doge
// C语言词法分析器 #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <string> #include <fstream> #include <sstream> #include <vector> using namespace std; /* 不要修改这个标准输入函数 */ void read_prog(string& prog) { char c; while(scanf("%c",&c)!=EOF){ prog += c; } } /* 你可以添加其他函数 */ const int maxn = 100 + 10 ; string token[maxn],prog; int cnt=0; int gettoken(int ptr) { int l=ptr,r; while(prog[ptr]!=' ' && prog[ptr]!='\n') ptr++; r=ptr; token[++cnt] = prog.substr(l,r-l); return r; } void token_divide() { int ptr=0; while(ptr<prog.length()){ while(prog[ptr]==' ' || prog[ptr]=='\n') ptr++; if(ptr>=prog.length()) break; ptr=gettoken(ptr); } // cout<<cnt<<endl; // for(int i=1;i<=cnt;i++) // cout<<token[i]<<endl; } struct SYM { double v; string type; string name; bool is_itg; }sym[maxn]; int tops; bool isreal; double s2d(string s) { double num1=0,num2=0;//123.4456 bool itg=1; int siz=0; for(int i=0;i<s.length();i++) { if(s[i]=='.') { itg=0; isreal=1; continue; } if(itg==1) { num1*=10; num1+=(int)(s[i]-'0'); } else { num2+=(s[i]-'0'); num2*=10; siz++; } } for(int i=0;i<=siz;i++) num2/=10; return num1+num2; } bool err; void TS() { int st=0; for(int i=1;i<=cnt;i++) { if(token[i]=="{") { int l=1; for(int j=1;j<i;j++) { if(token[j]==";") { isreal=0; sym[++tops].type=token[l]; sym[tops].name=token[l+1]; sym[tops].v=s2d(token[l+3]); l=j+1; if((isreal && sym[tops].type=="int") || (!isreal && sym[tops].type=="real")) { err=1; cout<<"error message:line 1,realnum can not be translated into int type"<<endl; } } } st=i+1; break; } } bool tf=0; for(int i=st;i<=cnt;i++) { if(token[i]=="if") { /* for(int j=i;j<=cnt;j++) { if(token[j]==";") { cout<<token[j-1]<<endl; i=j; break; } }*/ // i+2 - i+4 double x,y; tf=0; for(int j=1;j<=tops;j++) { if(token[i+2]==sym[j].name) { x=sym[j].v; // cout<<token[i+2]<<" "<<y<<endl; break; } } for(int j=1;j<=tops;j++) { if(token[i+4]==sym[j].name) { y=sym[j].v; // cout<<token[i+2]<<" "<<y<<endl; break; } } if(token[i+3]==">" && x>y) tf=1; else if(token[i+3]=="<" && x<y) tf=1; else if(token[i+3]==">=" && x>=y) tf=1; else if(token[i+3]=="<=" && x<=y) tf=1; else if(token[i+3]=="==" && x==y) tf=1; i=i+5; continue; } else if(token[i]=="}") { continue; } else { if((token[i]=="then" && tf==1) || (token[i]=="else" && tf==0)) { i++; } else if(token[i]=="then" || token[i]=="else") { for(int j=i;j<=cnt;j++) { if(token[j]==";") { i=j; break; } } continue; } int x; double y; for(int j=1;j<=tops;j++) { if(token[i]==sym[j].name) { x=j; break; } }//sym[x]是得到的结果 if(token[i+2][0]>='a' && token[i+2][0]<='z') { for(int j=1;j<=tops;j++) { if(token[i+2]==sym[j].name) { y=sym[j].v; // cout<<token[i+2]<<" "<<y<<endl; break; } } } else { y=s2d(token[i+2]); }//右侧第一个字符 for(int j=i+3;j<=cnt;j++) { if(token[j]==";") { i=j; // cout<<"end"<<token[j+1]<<endl; break; } // cout<<token[j]<<endl; double nt; if(token[j+1][0]>='a' && token[j+1][0]<='z') { for(int k=1;k<=tops;k++) if(token[j+1]==sym[k].name) { nt=sym[k].v; break; } } else { nt=s2d(token[j+1]); } if(token[j]=="+") y+=nt; else if(token[j]=="-") y-=nt; else if(token[j]=="*") y*=nt; else if(token[j]=="/") { if(nt==0) { err=1; cout<<"error message:line 5,division by zero"<<endl; break; } y/=nt; } } sym[x].v=y; // cout<<"end"<<sym[x].name<<" "<<sym[x].v<<endl; } } } void prints() { if(err==1) return ; for(int i=1;i<=tops;i++) { cout<<sym[i].name<<": "<<sym[i].v<<endl; } } void Analysis() { read_prog(prog); prog+='\n'; /* 骚年们 请开始你们的表演 */ /********* Begin *********/ token_divide(); err=0; TS(); prints(); /********* End *********/ }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)