1、编译原理实验报告本文档集合了编译原理大作业的实验报告加代码实验主要内容为用 C+实现了词法分析程序;语法语义以及四元式生成程序代码见附录,复制进 VS 后程序绝对可编译执行。文档代码为原创,谨慎使用(姚砺的大作业)实 验 设 计 一一、实验名称 词 法 分 析 程 序二、实验目的(1)设计一个词法分析程序,每调用一次就从源程序文件中顺序识别出一个单词符号,并返回该单词符号的内部编码、单词符号自身、行列位置信息。(2)要能处理单行注释。三、实验内容及要求单词种类与识别规则(1) 标识符:首字符为字母或下划线,其后由字母、数字或下划线组成、长度不超过 255 个字符;(2) 整数:由 1 到 8
2、个数字组成。(3) 小数:数字串 1 . 数字串 2,其中:数字串 1 由 1-8 个数字符组成;数字串 2 由 0-8 个数字符组成,即:数字串 2 可以为空。(4) 字符串:由一对“”括起来的符号串,长度不超过 255 个字符;(5) 保留字:if 、else 、while、do、integer、float、string、input、output、and、or、function、end、def、as 、begin(6) 数学运算符: 、*、/、= (7) 比较运算符: 、=、=0 elsereturn false;(2)相关函数void push_in_token( Token token
3、 ) /进表操作S.name = token.value;S.type = -1;S.value = false;ST.push_back( S );vector : iterator find_token( Token token ) /查表操作it = find_if( ST.begin(), ST.end(), bind2nd( compare(),token.value );return it;(2) 测试数据和结果(4)设计思路语义部分主要采用符号表结构,符号表中记录了每个非终结符的信息。 (名称,类型,是否赋值) 。然后再程序中每次调用 Token 函数发现读取到标识符时都进行查表
4、操作。根据查表结果进行相关分析。在赋值函数中,如果查表找到其信息就说明重复定义。再其余函数中1.没有找到说明为声明就使用。 2.找到发现未赋值说明未赋值就引用。(5)语义部分小总结假如只实现以上 3 个功能语义部分并不难,关键是符号表的构建以及进表查表等操作。在这一部分我使用了仿函数和绑定器进行查表。由于我把相应表结构都存在 vector 内,导致查找结构内成员信息的不便,但是自己写一套查找操作代码估计效率不高,索性使用仿函数进行查找,泛型操作一般效率较高而且代码较少也很清晰。假如时间更充足一点其实还可以把数据类型匹配这一部分拓展一下,毕竟也是查表比较,但是时间有限只好先完成要求的 3 个任务
5、。3、四元式分析设计(1)相关数据结构struct Quaternary /四元式结构int serial;string op;string v1;string v2;string result;Q;stack operator_stack; /操作数堆栈stack operand_stack; /操作符堆栈(2)相关函数Quaternary Quaternary_generater( int serial, string op, string v1, string v2, string result ) /四元式生成函数Q.serial = serial;Q.op = op;Q.v1 = v
6、1;Q.v2 = v2;Q.result = result;return Q;void Quaternary_maker()while( !operand_stack.empty() operator_stack.pop();v1 = operand_stack.top();operand_stack.pop();v2 = operand_stack.top();operand_stack.pop();res = resultr;r+;Q = Quaternary_generater( serial, op, v1, v2, res );serial+;QV.push_back( Q );/f
7、or( it2=QV.begin(); it2!=QV.end(); it2+ ) /找回真出口if( (*it2).result=“null“ )stringstream ss; ss 2. 3. function id ( ) end function 4. begin 语句 语句 end 5. |6. def id , id as ;7. integer | float | string8. input id , id ;9. output , ;10. id = ;11. if else 12. while do 13. +| 14. *|/ 15. id | con | deci |
8、 ( )14. and | or 15. 16. | = | = | =“ ; /运算符 6string text; /记录标识符 1string contentMAXLINE; /保存从文件读取的内容int i=0; /i 为字符游标int templine = 0;int scan( string s ,int line )int j, flag =0;text = “; /赋空 textwhile( contentlinei= ) /判断空格i+; /是空格跳过if( (contentlinei=65 text += contentlinei+1;i=i+2;return 7;else
9、text = contentlinei;i+; return 7;if( contentlinei=“ ) /判断是否为字符串text += contentlinei;i+;while( contentlinei!=” )text += contentlinei;i+;text += contentlinei;i+;return 4;if( contentlinei=/ ) /判断是否为注释if( contentlinei+1=/)i=contentline.length();return 0; /如果为行注释那么游标指向行末elseif( contentlinei+1=* )i=i+2;wh
10、ile( contentlinei!=* | contentlinei+1!=/ )if( i=contentline.length() )line+;i=0;elsei+;i=i+2;templine = line;return -1; /-1 代表块注释else text = contentlinei;i+; return 0;return 0;int main()ifstream infile(“ceshi1.txt“,ios:in);if( infile )cout #include #include #include #include #include #include #inclu
11、de #include #include #include #include #include #include #define MAXLINE 30using namespace std;/标识符 1,整数 2,小数 3,字符串 4,保留字 5,数学运算符 6,比较运算符 7,逻辑运算符 8,分隔符 9string key14=“if“,“else“,“while“,“do“,“float“,“string“,“begin“,“end“,“def“,“integer“,“input“,“output“,“as“,“function“; /保留字string border5= “;“ , “
12、, “ , “(“ , “)“ ; /分隔符 5string arithmetic9=“+“ , “-“ , “*“ , “/“ ,“ , “=“ ; /运算符 6string text; /记录标识符 1string contentMAXLINE; /保存从文件读取的内容string resultMAXLINE = “t1“,“t2“,“t3“,“t4“,“t5“,“t6“,“t7“,“t8“,“t9“,“t10“;/*/*语法语义 各产生式 函数*/void chengxu();void hanshukuai();void hanshu();void yujukuai();void yuj
13、u();void bianliangdingyiyuju();void shujuleixing();void shuruyuju();void shuchuyuju();void fuzhiyuju();void fenzhiyuju();void xunhuanyuju();void biaodashi();void xiang();void yinzi();void buerbiaodashi();void guanxibiaodashi();void guanxi();void error();void Quaternary_output();void Quaternary_maker
14、();int i=0,k=1,numline,mode; /i 为字符游标,k 为行号,numline 记录了文件总行数int templine = 0;int errornum = 0;int warningnum = 0;int r = 0, serial = 1;string op,v1,v2,res;struct Tokenstring value; /值int mode; /类型int row; /行int col; /列token;struct Symtable /符号表结构string name;int type;bool value;S;struct Quaternary /四
15、元式结构int serial;string op;string v1;string v2;string result;Q;Quaternary Quaternary_generater( int serial, string op, string v1, string v2, string result ); /函数声明vector ST;vector : iterator it;vector QV;vector : iterator it2;stack operator_stack; /操作数堆栈stack operand_stack; /操作符堆栈struct compare: binar
16、y_function /仿函数和绑定器bool operator()( Symtable s, string str) constif (s.name= str)return true;elsereturn false;void push_in_token( Token token ) /进表操作S.name = token.value;S.type = -1;S.value = false;ST.push_back( S );vector : iterator find_token( Token token ) /查表操作it = find_if( ST.begin(), ST.end(),
17、 bind2nd( compare(),token.value );return it;int scan( string s ,int line )int j, flag =0;text = “; /赋空 textwhile( contentlinei= ) /判断空格i+; /是空格跳过if( (contentlinei=65 text += contentlinei+1;i=i+2;return 7;else text = contentlinei;i+; return 7;if( contentlinei=“ ) /判断是否为字符串text += contentlinei;i+;whil
18、e( contentlinei!=” )text += contentlinei;i+;text += contentlinei;i+;return 4;if( contentlinei=/ ) /判断是否为注释if( contentlinei+1=/)i=contentline.length();return 0; /如果为行注释那么游标指向行末elseif( contentlinei+1=* )i=i+2;while( contentlinei!=* | contentlinei+1!=/ )if( i=contentline.length() )line+;i=0;elsei+;i=i+
19、2;templine = line;return -1; /-1 代表块注释else text = contentlinei; i+;return 6; /说明是除号/ text = contentlinei;i+; return 0;return 0;Token getToken() /该函数用于取字符for( ; k filename;ifstream infile( filename,ios:in);/此处在 VC 上可能编译不过 可改为 ifstream infile( “ceshi1.txt“,ios:in); 手动输入文件名if( infile )cout “ “ token.va
20、lue;cout endl;cout endl;warningnum+;void chengxu()token = getToken();hanshukuai();void hanshukuai()hanshu();while( token.value=“function“ )hanshu();void hanshu()if( token.value=“function“ )token = getToken();elseerror( token, “缺少函数声明标志或函数声明标志不正确“ );if( token.mode=1 )token = getToken();elseerror( tok
21、en, “函数名不正确“ );if( token.value=“(“ )token = getToken();elseerror( token, “函数名后应出现左括号“ );if( token.value=“)“ )token = getToken();elseerror( token, “函数名后应出现右括号“ );yujukuai();if( token.value=“end“ )token = getToken();elseerror( token, “缺少函数结束符 end“ );if( token.value=“function“ )token = getToken();elsee
22、rror( token, “缺少关键字 function“ );void yujukuai()if( token.value=“begin“ )token = getToken();elseerror( token, “缺少关键字 begin“ );yuju();while( token.value=“def“ | token.value=“while“ | token.value=“input“ | token.value=“output“ | token.value=“if“ | token.mode =1 )yuju();if( token.value=“end“ )token = getToken();elseerror( token, “缺少语句块结束符 end“ );void yuju()if( token.value=“def“ )bianliangdingyiyuju();if( token.value=“while“ )xunhuanyuju();if( token.value=“input“ )shuruyuju();if( token.value=“output“ )shuchuyuju();if( token.mode=1 )fuzhiyuju();if( token.value=“if“ )fenzhiyuju();