实验报告
分析该语言的词法和语法规则,分析其编译器的运行命令和代码组成结构
词法规则
下面是LEX中的变量声明
定义段可以包含任意的C语言文件,符号说明,其代码会被直接拷贝到生成的扫描器代码文件中
声明示例如下
%{
…
%}
digit [0-9]
number {digit}+
letter [a-zA-Z]
identifier {letter}+
newline \n
whitespace [ \t]+
下面是一些关键字,规则段利用正则表达式来匹配模式,每当成功匹配一个模式,就对应其后“{ }” 中的代码。
语法规则示例如下
%%
…
%%
"if" {return IF;}
"then" {return THEN;}
"else" {return ELSE;}
"end" {return END;}
"repeat" {return REPEAT;}
"until" {return UNTIL;}
"read" {return READ;}
"write" {return WRITE;}
":=" {return ASSIGN;}
"=" {return EQ;}
"<" {return LT;}
"+" {return PLUS;}
"-" {return MINUS;}
"*" {return TIMES;}
"/" {return OVER;}
"(" {return LPAREN;}
")" {return RPAREN;}
";" {return SEMI;}
{number} {return NUM;}
{identifier} {return ID;}
{newline} {lineno++;}
{whitespace} {/* skip whitespace */}
"{" { char c;
do
{ c = input();
if (c == EOF) break;
if (c == '\n') lineno++;
} while (c != '}');
}
. {return ERROR;}
%%
int yywrap()
{ return 1;}
TokenType getToken(void)
{ static int firstTime = TRUE;
TokenType currentToken;
if (firstTime)
{ firstTime = FALSE;
lineno++;
yyin = source;
yyout = listing;
}
currentToken = yylex();
strncpy(tokenString,yytext,MAXTOKENLEN);
if (TraceScan) {
fprintf(listing,"\t%d: ",lineno);
printToken(currentToken,tokenString);
}
return currentToken;
}
添加//
和 /* */
的规则
"//" { char c;
do
{ c = input();
if (c == EOF) break;
} while (c != '\n');
}
"/*" { char c;
int d=0;
do
{ c = input();
if (c == '/'&&d==1)
d=2;
else if(c !='/'&&d==1)
d=0;
if (c == EOF) break;
if (c == '\n') lineno++;
if (c == '*') d=1;
} while (d != 2);
}
测试过程
语法规则
需要先修改tiny.l使其多识别一种符号
"while" {return WHILE;}
语法规则主要在YACC中,添加 while 语法在tiny.y文件中增加声明和定义
%token WHILE
while_stmt : WHILE exp THEN stmt_seq END
{ $$ = newStmtNode(WHILEK);
$$->child[0] = $2;
$$->child[1] = $4;
}
;
newStmtNode(WHILEK)
还需要修改cgen
文件,增加对于WHILEK
的处理
case WHILEK :
if (TraceCode) emitComment("-> while") ;
p1 = tree->child[0] ;
p2 = tree->child[1] ;
/* generate code for test expression */
savedLoc1 = emitSkip(0) ;
cGen(p1);
savedLoc2 = emitSkip(1) ;
emitComment("while: jump to else belongs here");
cGen(p2);
emitRM_Abs("LDA",pc,savedLoc1,"jmp to end") ;
/* recurse on then part */
currentLoc = emitSkip(0) ;
emitBackup(savedLoc2) ;
emitRM_Abs("JEQ",ac,currentLoc,"while: jmp to else");
emitRestore() ;
if (TraceCode) emitComment("<- while") ;
break; /* WHILEK_k */
tny文件修改为,从10 倒序打印
{ Sample program
in TINY language -
computes factorial
}
read x
// sssss
/* ddd */
; { input an integer }
if 0 < x then { don't compute if x <= 0 }
fact := 1;
repeat
fact := fact * x;
x := x - 1
until x = 0;
write fact { output factorial of x }
end;
y := 10;
while 0 < y then
y := y - 1;
write y
end
语法树:
运行的效果: