tiny 实验报告

实验报告

分析该语言的词法和语法规则,分析其编译器的运行命令和代码组成结构

词法规则

下面是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);
                }

测试过程

image-20200111132822132

语法规则

需要先修改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

语法树:

image-20200111153138350

运行的效果:

image-20200111153205806


   转载规则


《tiny 实验报告》 Hook 采用 知识共享署名 4.0 国际许可协议 进行许可。
  目录