📄 micro说明.txt
字号:
计划:
如果从当前(04.06)的版本开始,(包含了Declare,Add, Sub, Store操作,中间代码格式为op A,B,C A源操作数,B目的操作数,保存结果到C)。
1. 输出到文件。 ok
2. 实现执行机构(MVM Micro Virtual Mechine)
3. 函数调用
optional:
3. 实现地址(当前使用带符号的生成格式,如果生成类似指令的结果代码,那么需要将生成的代码中的符号转换成相对地址)
4. 看看能不能实现链接、加载
带语义处理的表示: #xxxx表示对应的处理函数
<program> -> #start begin <statement list> end
<statementlist> -> <statement { <statement> }
<statement> -> <ident> := <expression> #assign ;
<statement> -> <read( <id list> );
<statement> -> <write>( <expr list> );
<id list> -> <ident> #read_id {, <ident> #read_id }
<expr list> -> <expression> #write_expr {, <expression> #write_expr }
<expression> -> <primary> { <add op> <primary> #gen_infix }
<primary> -> ( <expression> )
<primary> -> <ident>
<primary> -> INTLITERAL #process_literal
<add op> -> PLUSOP #process_op
<add op> -> MINUSOP #process_op
<ident> -> ID #process_id
<system goal> -> <program> SCANEOF #finish
扩展后的语法:(需要各个first集不相交) 修改<id list>为<read list>, <expr list>为<write list>
<system goal> -> <program> SCANEOF #finish
<program> -> #start <function> #process_func_def {, <function> #process_func_def }
<function> -> function <ident> ( <param list> ) begin <statement list> end
<function> -> function <ident> ( ) begin <statement list> end
<statementlist> -> <statement> { <statement> }
<statement> -> <ident> := <expression> #assign ;
<statement> -> read( <read list> );
<statement> -> write ( <write list> );
<statement> -> <ident> ( { <argument list> } ) #process_func_call;
<param list> -> <ident> #process_param {, <ident> #process_param }
<argument list> -> <ident> #process_argu {, <ident> #process_argu }
<read list> -> <ident> #read_id {, <ident> #read_id }
<write list> -> <expression> #write_expr {, <expression> #write_expr }
<expression> -> <mul expr> { <add op> <mul expr> #gen_infix }
<mul expr> -> <primary> { <mul op> <primary> }
<primary> -> ( <expression> )
<primary> -> <ident>
<primary> -> INTLITERAL #process_literal
<add op> -> PLUSOP #process_op
<add op> -> MINUSOP #process_op
<mul op> -> MULOP #process_op
<mul op> -> DIVOP #process_op
<ident> -> ID #process_id
对词法的影响:
关键字: begin end read write function
词法记号:
UNDEFINE,
// 1 2 3 4 5 6 7 8 9 10
BEGIN, END, READ, WRITE, ID, INTLITERAL, LPAREN, RPAREN, SEMICOLON, COMMA,
// 11 12 13 14 15 16 17
ASSIGNOP, PLUSOP, MINUSOP, FUNCTION, MULOP, DIVOP, SCANEOF
} token;
对语义分析来说,需要添加process_func,
<program> -> #start <function> #process_func {, <function> }
中间代码种类添加:
函数定义
Declare xxx, function
Declare xx, Param
Declare yy, Param
乘除运算
Mul a, b, c
Div a, b, c
函数调用
Argu xx
Argu yy
Call xxx
对应地,定义局部和全局符号表(在当前语法规则下,还没有全局数据变量)
全局符号表包含全局变量名称、函数名称
局部符号表仅仅包含编译时的某个函数内的名称
function HelloWorld (a, b)
begin
write(a, a);
end
function Main (a, b)
begin
write(a, b);
HelloWorld(a, b);
end
如果加上乘操作,<expression>怎么定义? 1+2*3 2*1+3 1*2+3*1 (1+2)*(1*3)
如果加上<mul op>那么将无法判断是 <mul op>还是<ident>需要LL(1)
<expression> -> <mul expr> { <add op> <mul expr> #gen_infix }
<mul expr> -> <primary> { <mul op> <primary> }
<primary> -> ( <expression> )
<primary> -> <ident>
<primary> -> INTLITERAL #process_literal
<add op> -> PLUSOP #process_op
<add op> -> MINUSOP #process_op
<mul op> -> MULOP #process_op
<mul op> -> DIVOP #process_op
<ident> -> ID #process_id
如果代码中没有地址机制,基本上没有什么意义。
如果加上地址操作(&, *要尽量简单),则又需要继续修改词法、语法分析器。
===========================================
教训
===========================================
虽然自认为对C比较了解,但是现在犯了一个大的错误,下面两个函数的参数是结构体,包含有一个字符型数组,程序的功能包括
返回结构体中数组的地址(例如return s.text;)。但是在修改前的程序中,返回的是参数栈上结构体所含的地址(虽然虽然知
道栈的临时性,但是原来首先想到的是结构体的整体拷贝,那么“内容”就是相同的,既然是相同的内容那么“无妨”编写下面
修改前的代码)
char * extract(expr_rec s); 修改前
char * extract(expr_rec & s); 修改后
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -