构造编译器的第一步

/* Power by Keamou@CS@CITS@NKU */

1           用自然语言结合代码实例描述你的C语言编译器所支持语言特性的语法和语义。

答:

*         赋值(=)语句

语法结构是:

变量名 = 表达式

语义是:

将表达式计算所得的值赋给变量。

产生式为:

stmt → id = expr

*         if 分支语句

语法结构是:

if(判定条件语句)动作程序段

else动作程序段二

语义是:

a)    判断条件不成立?跳到c

b)   执行动作程序段一,跳到d

c)    执行动作程序段二

d

产生式为:

stmt → if expr then stmt

      | if expr then stmt else stmt

*         while 循环语句

语法结构是:

while(循环判定语句)循环体

语义是:

a)    循环判定语句不成立?跳到c

b)   执行循环体,跳到a

c

产生式为:

stmt → while ( expr ) stmt

*         for循环语句

语法结构是:

for (循环初始化语句; 循环判定条件; 循环增量语句)

       循环体(可以任意的语句——简单语句、条件分支、循环、复合语句

语义是:

a)        执行循环初始化语句

b)        循环判定条件不成立?跳到e)

c)         执行循环体

d)       执行循环增量语句,跳到b)

e)

产生式为:

stmt → for( expr1 , expr2 ,expr3 stmt

*         函数

语法结构是:

函数名(参数){ 代码段 }

语义是:

遇到函数 函数名(参数) 时调用函数的代码段

产生式为:

func → ( type ) term ( params ) { stmt }

*         变量声明

语法结构是:

变量类型 变量名列表;

语义是:

在内存开辟相应的空间以存储变量信息

产生式为:

expr → type idlist

type → int | char | double | float

idlist → id | id , idlist

 

2           为每个语言特性编写等价的汇编语言框架,上机验证其正确性。

答:

*         赋值(=)语句

value = tmp 的汇编代码:

MOV AXtmp

MOV valueAX

*         if 分支语句

if(a>3)b++; else b--; 的汇编代码:

MOV AX3

CMP aAX

JLE tmpN

MOV AXb

MOV BX1

ADD AXBX

MOV bAX

JMP tmpM

tmpN

MOV AXb

MOV BX1

SUB AXBX

MOV bAX

tmpM

*         while 循环语句

whilea>3b++;的汇编代码是:

tmpN

MOV AX3

CMP aAX

JLE tmpM

MOV AXb

MOV BX1

ADD AX

MOV bAX

JMP tmpN

tmpM

*         for循环语句

forint i=0i<3i++b++;的汇编代码:

MOV AX0

MOV iAX

tmpN

MOV AX3

CMP iAX

JLE tmpM

JMP tmpO

tmpP

MOV AXi

MOV BX1

ADD AXBX

MOV iAX

JMP tmpN

tmpO

MOV AXb

MOV BX1

ADD AXBX

MOV bAX

JMP tmpP

tmpM

*         函数

先是通过压栈传参,后函数声明:

Funct:

Stmt转化的汇编代码段

Funct ENDS

函数调用:

CALL Funct

*         变量声明

汇编代码为:

变量名 DB变量大小 DUP(?)

 

3          考虑如何让你的编译器支持输入输出的语言特性。建议:可借助MASM32包对msvcrt动态链接库的支持,实现对printf等库函数的直接调用。详细可参考MASM32包中/tools/makecimp/vcrtdemo目录中使用msvcrt的例子。

答:

在翻译产生的汇编代码前加上一段引用声明:

include    /masm32/include/msvcrt.inc

includelib  /masm32/lib/msvcrt.lib

【注】此代码中的路径表示masm32的安装目录在当前目录下。

当遇到printf()函数时,翻译成相应的汇编代码:

invoke crt_printf, SADD("<打印语句> <参数> <打印语句>"),参数列表

例如:翻译printf(“my %d masm/n”,mytime);得汇编代码如下

invoke crt_printf, SADD(“my %d masm”, 13,10),OFFSET mytime

 

4           尝试编写简单的目标代码生成程序。下面是一个简单的C程序的语法树。设计程序,对语法树进行遍历,访问到某个语言结构(树的节点、子树)时将其转换为汇编语言代码。

答:

根据语法树,设计翻译模式,写成Yacc代码如下:

lines       :      lines prog '/n'      { printf("%s/n", $2); }

              |     lines '/n'

              |

              ;

prog    :   mainfunction

        ;

mainfunction

        :   'm''a''i''n' params {printf("DATA SEGMENT/ntmp%d DB ?/n",tmp);}  '{' stmts '}' {printf("CODE ENDS/nEND START/n");}

        ;

params  :   '(' type ')'

        ;

stmts   :   stmt{printf("CODE SEGMENT/n ASSUME DS:DATA,CS:CODE,ES:DATA/nSTART:/n");}stmts

        |   stmt

        ;

stmt    :   'f''o''r''(' expr ';' {printf("JUDGE%d/n",tmp);}expr ';' {printf("EXPR%d:/n",tmp);}

             expr {printf("JMP JUDGE%d:/n",tmp);}

            ')'{printf("STMT%d:/n",tmp);} stmt {printf("JMP EXPR%d/nOUT%d:/n",tmp,tmp);}

        |   expr ';'

        |   type vars ';' {printf("DATA ENDS/n");}

        ;

       

type    :   'i''n''t'' '  {getsize(sizeof(int));}

        |   'v''o''i''d'

        ;

       

vars    :   var ',' vars  {printf("%s DB %d DUP(?)/n",$1,typesize);}

        |   var           {printf("%s DB %d DUP(?)/n",$1,typesize);}

        ;

       

var     :   'a'                          { strcpy($$, "a"); }

        |   (为节省空间,其他字母省略)

        |   'i'                         { strcpy($$, "i"); }

        |   (为节省空间,其他字母省略)

        ;

 

expr    :   var '<' '=' expr        { gettmp($$); getcode($$,$1,$4,"<=");}

        |   var '+' expr            { gettmp($$); getcode($$,$1,$3,"+");}

        |   var  '=' expr            { gettmp($$); getcode($$,$1,$3,"=");}

        |   var

        |   digit

        ;

digit   :   con            { strcpy($$, $1); }

        |   con digit      { strcpy($$, $1); strcat($$, $2);}

        |

        ;

       

con       :      '0'                         { strcpy($$, "0"); }

              |     '1'                         { strcpy($$, "1"); }

              |     '2'                         { strcpy($$, "2"); }

              |     '3'                         { strcpy($$, "3"); }

              |     '4'                         { strcpy($$, "4"); }

              |     '5'                         { strcpy($$, "5"); }

              |     '6'                         { strcpy($$, "6"); }

              |     '7'                         { strcpy($$, "7"); }

              |     '8'                         { strcpy($$, "8"); }

              |     '9'                         { strcpy($$, "9"); }

              ;

上述文法实现题目中要求的遍历语法树,其中还包括识别多位十进制整数的实现。

具体代码请看附件代码包。

Yacc程序编译通过后放在VC6.0下再编译执行得如下结果:

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值