利用状态机完成Tiny词法分析

考虑分析中用到的Tokentype,由各种值。所有的token取值都在里面了

typedef enum 
    /* book-keeping tokens */
   {ENDFILE,ERROR,
    /* reserved words */
    IF,THEN,ELSE,END,REPEAT,UNTIL,READ,WRITE,
    /* multicharacter tokens 多字符tokens分为两类ID,NUM。比如a=3 a是ID 3是NUM类型的值*/
    ID,NUM,
    /* special symbols 比如a=3,=就是ASSIGN,操作符*/
    ASSIGN,EQ,LT,PLUS,MINUS,TIMES,OVER,LPAREN,RPAREN,SEMI
   } TokenType;

一些其他变量:

/* MAXRESERVED = the number of reserved words */
#define MAXRESERVED 8

extern FILE* source; /* source code text file */
extern FILE* listing; /* listing output text file */
extern FILE* code; /* code text file for TM simulator */

extern int lineno; /* source line number for listing */

最后还有for tracing的部分,设置对应变量为True会在解析过程中打印状态信息

词法分析部分:
在这里插入图片描述

/* states in scanner DFA */
typedef enum
   { START,INASSIGN,INCOMMENT,INNUM,INID,DONE }
   StateType;

既然是状态机,首先要记录状态,StateType就是用来记录状态机的状态,根据当前不同的状态和获取的字符选择下一步操作。图中六个状态正好对应enum的六个值。
这里要注意,每识别一个用空格隔开的单词就重复从START到DONE的步骤。

/* lexeme of identifier or reserved word */
char tokenString[MAXTOKENLEN+1];

应该是识别identifier用

  /* index for storing into tokenString */
   int tokenStringIndex = 0; #tokenString下标,分析是一个一个字符分析的,总要有个容器(tokenString)临时存放这个半成品的token
   /* holds current token to be returned */
   TokenType currentToken; #记录当前token的值
   /* current state - always begins at START */
   StateType state = START; #记录当前状态的值
   /* flag to indicate save to tokenString */
   int save; #判断当前字符是否记录进tokenString,如果是空白等无意义字符就不记录

图上省略了一些对操作符±<>*的判断,直接在other中没有体现出来。
这些操作符也有单独的token表示

     switch (state)
     { case START:
         if (isdigit(c))
           state = INNUM;
         else if (isalpha(c))
           state = INID;
         else if (c == ':')
           state = INASSIGN; #如果是:,就进入赋值状态(赋值语句)比如语句fact := 1;
         else if ((c == ' ') || (c == '\t') || (c == '\n'))
           save = FALSE;
         else if (c == '{')
         { save = FALSE;
           state = INCOMMENT;
         }
         else
         { state = DONE;
           switch (c)
           { case EOF:
               save = FALSE;
               currentToken = ENDFILE;
               break;
             case '=':
               currentToken = EQ;
               break;
             case '<':
               currentToken = LT;
               break;
				。。。
           }
         }
         break;

当判断出token结束时,执行ungetNextChar函数。

/* ungetNextChar backtracks one character
   in lineBuf */
static void ungetNextChar(void)
{ if (!EOF_flag) linepos-- ;}
       case INNUM:
         if (!isdigit(c))
         { /* backup in the input */
           ungetNextChar();  #理论上来说数字必须是全部是digit,一旦出现不是数字了,就默认该token已经结束。这时这个字符就要unget一下。
           save = FALSE;
           state = DONE;
           currentToken = NUM;
         }
         break;

符号表:
记录了这些信息

  fprintf(listing,"Variable Name  Location   Line Numbers\n");
  fprintf(listing,"-------------  --------   ------------\n");
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值