动手实现编译器(八)——IF条件语句

在上一节中,我们实现了比较运算符的计算,现在,我们可以容易地实现IF条件语句。

首先我们看IF语句的SysY语言的定义:

语句: Stmt → LVal ‘=’ Exp ‘;’ | ‘if’ '( Cond ‘)’ Stmt [ ‘else’ Stmt ]

修改词法分析

首先,我们要增加新的单词类型,表示"{","}","(",")",“if”,"else"六种符号。

// 单词类型
enum
{
   
   
    T_EOF,
    T_ADD, T_SUB, T_MUL, T_DIV, T_MOD, T_EQ, T_NE, T_LT, T_GT, T_LE, T_GE,
    T_INT, T_SEM, T_PRINT, T_EQU, T_IDENT, T_KEYINT, T_IF, T_ELSE,
    T_LBRACE, T_RBRACE, T_LPAREN, T_RPAREN
};

然后,我们要修改扫描函数,使之能识别到新的单词类型。

// 加入"if"和"else"的匹配
int match_keyword(char *s)
{
   
   
    switch (*s)
    {
   
   
        case 'e':   if(!strcmp(s, "else"))  return (T_ELSE);
                    break;
        case 'i':   if(!strcmp(s, "if"))    return (T_IF);
                    if(!strcmp(s, "int"))   return (T_KEYINT);
                    break;
        case 'p':   if(!strcmp(s, "print")) return (T_PRINT);
                    break;
    }
    return 0;
}

// scan()函数中加入解析"{","}","(",")"
case '{':   t->token = T_LBRACE; break;
case '}':   t->token = T_RBRACE; break;
case '(':   t->token = T_LPAREN; break;
case ')':   t->token = T_RPAREN; break;

同时添加新的单词匹配函数:

// 检查当前单词是否为"{",并获取下一个单词
void lbrace()
{
   
   
    match(T_LBRACE, "{");
}

// 检查当前单词是否为"}",并获取下一个单词
void rbrace()
{
   
   
    match(T_RBRACE, "}");
}

// 检查当前单词是否为"(",并获取下一个单词
void lparen()
{
   
   
    match(T_LPAREN, "(");
}

// 检查当前单词是否为")",并获取下一个单词
void rparen()
{
   
   
    match(T_RPAREN, ")");
}

修改语法分析

为了后面的代码更容易实现,我暂时强制规定语法:

编译单元: CompUnit → Block
语句块: Block → ‘{’ { BlockItem } ‘}’
语句块项: BlockItem → Stmt

这些规则的目的是强制代码以{Stmt}的语句块形式书写,目的是为了避免复合语句的else的歧义性。由于这是一个正在进行的项目,因此我会新增一些规则,同时在后面会撤消这些规则并将其重构。后面的章节中,我会使{Stmt}为可选。

分析复合语句块

将原来分析句子的statements()函数改为分析语句块的Block_statement()函数

// 分析语句块并返回其AST
struct ASTnode *Block_statement()
{
   
   
    struct ASTnode *left = NULL;
    struct ASTnode *tree;
    // 匹配"{"
    lbrace();
    while (1)
    {
   
   
        switch (Token.token)
        {
   
   
            case T_PRINT:  tree = print_statement();        break;
            case T_KEYINT: var_declaration();  tree = NULL; break;
            case T_IDENT:  tree = assignment_statement();   break;
            case T_IF:     tree = if_statement();           break;
            case T_RBRACE: rbrace();    return (left); //遇到"}"时,返回AST树
            default:    fprintf(stderr, "Syntax error, token:%d on line %d\n", Token.token, Line);
            			exit(1);
        }
        // 对于每个新树,如果左子树为空,则将其保存在左子树中,
        // 否则将左子树和新树合并
        if (tree)
        {
   
   
            if (left == NULL)   left = tree;
            else    left = mkastnode(A_GLUE
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值