⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 micro说明.txt

📁 现代编译原理C语言实现中的第二章的编译器实现。并在书中的基础上有所改变。包括词法语法分析及汇编代码生成。
💻 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 + -