Press "Enter" to skip to content

ucc编译器(语义分析)

本站内容均来自兴趣收集,如不慎侵害的您的相关权益,请留言告知,我们将尽快删除.谢谢.

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

 

符合语法的代码,不一定符合语义。这句话听上去很拗口,我们不妨举个例子,假设我们定义了一个变量int a;,这个时候我们不能再定义一个int a吧。这个是关于变量的例子。

 

我们还可以举一个函数的例子,假设一个函数没有返回值,但是在实现的时候,出现了一个return true的语句,这个是不是也不合理。

 

因为语法树本身已经创建好了,这个时候只要按照语法树的结构往下层层递进就可以了,基本处理方法类似于二叉树的后序遍历。

 

1、语义解析的入口

 

void CheckTranslationUnit(AstTranslationUnit transUnit)

 

2、每一个语法解析的地方都有一个语义解析的文件

 

declchk.c

 

https://github.com/sheisc/ucc162.3/blob/master/ucc/ucl/declchk.c

 

exprchk.c

 

https://github.com/sheisc/ucc162.3/blob/master/ucc/ucl/exprchk.c

 

stmtchk.c

 

https://github.com/sheisc/ucc162.3/blob/master/ucc/ucl/stmtchk.c

 

3、symbol.c

 

语义解析关键的一个文件

 

https://github.com/sheisc/ucc162.3/blob/master/ucc/ucl/symbol.c

 

变量存不存在、函数存不存在、类型对不对,这些都和symbol.c息息相关。

 

symbol.c中的addTag和addFunction就会出现在不同的语义检查文件中。

 

4、不失一般性,我们分析一下stmtchk.c

 

4.1 入口函数

 

static AstStatement CheckStatement(AstStatement stmt)
{
return (* StmtCheckers[stmt->kind - NK_ExpressionStatement])(stmt);
}

 

4.2 检查case-statement

 

/**
case-statement:
case  constant-expression :statement
 Constraints 
A case or default label shall appear only in a switch statement.
 Further constraints on such labels are discussed under the switch
 statement.
 Even the following code is legal:
 int a = 5;
switch(a){
printf("123.\n");---------- these are dead-code.
break;
case 3:
printf("3.\n");
printf("this printf is not part of case-statment from syntactic view.\n");
case 2:
printf("2.\n");
}
 */static AstStatement CheckCaseStatement(AstStatement stmt)
{
AstCaseStatement caseStmt = AsCase(stmt);
AstSwitchStatement swtchStmt;
// We have pushed the current switch statement in CheckSwitchStatement(...)
swtchStmt = (AstSwitchStatement)TopStatement(CURRENTF->swtches);
if (swtchStmt == NULL)
{
Error(&stmt->coord, "A case label shall appear in a switch statement.");
return stmt;
}
caseStmt->expr = CheckConstantExpression(caseStmt->expr);
if (caseStmt->expr == NULL)
{
Error(&stmt->coord, "The case value must be integer constant.");
return stmt;
}
caseStmt->stmt = CheckStatement(caseStmt->stmt);
caseStmt->expr = FoldCast(swtchStmt->expr->ty, caseStmt->expr);
AddCase(swtchStmt, caseStmt);
return stmt;
}

 

case-statement最容易出现的问题,一个是外面没有switch语句,一个是value数值不是整数。

 

4.3 检查for-statement

 

/**
 iteration-statement:
 while (  expression )statement
 do  statement while (expression ) ;
 */static AstStatement CheckLoopStatement(AstStatement stmt)
{
AstLoopStatement loopStmt = AsLoop(stmt);
PushStatement(CURRENTF->loops,    stmt);
PushStatement(CURRENTF->breakable, stmt);
// Adjust expr's type to Pointer(...)  when its type is FUNCTION/ARRAY
loopStmt->expr = Adjust(CheckExpression(loopStmt->expr), 1);
if (! IsScalarType(loopStmt->expr->ty))
{
Error(&stmt->coord, "The expression in do or while statement shall be scalar type.");
}
loopStmt->stmt = CheckStatement(loopStmt->stmt);

PopStatement(CURRENTF->loops);
PopStatement(CURRENTF->breakable);
return stmt;
}

 

循环语句的问题主要就是判断expression是不是标量。

 

4.4 检查break-statement

 

// break;
static AstStatement CheckBreakStatement(AstStatement stmt)
{
AstBreakStatement brkStmt = AsBreak(stmt);
brkStmt->target = TopStatement(CURRENTF->breakable);
if (brkStmt->target == NULL)
{
Error(&stmt->coord, "The break shall appear in a switch or loop");
}
return stmt;
}

 

break语句主要是判断在不在循环里面。

 

4.5 检查default-statement

 

/**
default-statement
default :  statement
 */static AstStatement CheckDefaultStatement(AstStatement stmt)
{
AstDefaultStatement defStmt = AsDef(stmt);
AstSwitchStatement swtchStmt;
swtchStmt = (AstSwitchStatement)TopStatement(CURRENTF->swtches);
if (swtchStmt == NULL)
{
Error(&stmt->coord, "A default label shall appear in a switch statement.");
return stmt;
}
if (swtchStmt->defStmt != NULL)
{
Error(&stmt->coord, "There shall be only one default label in a switch statement.");
return stmt;
}
defStmt->stmt = CheckStatement(defStmt->stmt);
swtchStmt->defStmt = defStmt;
return stmt;
}

 

default语句主要有两个问题,一个是判断在不在switch语句内,一个是判断是不是只有一个default statement。

 

4.6 总结

 

statement语义分析的部分大同小异,主要就是把可能出现的问题罗列一遍,一般来说,如果没有问题的话,就会认为语句是没有问题的,可以进行后面二进制翻译工作了。

Be First to Comment

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注