yacc语法规则的语义

时间:2016-09-04 20:43:50

标签: c yacc

我一直在尝试使用flex和yacc编写一个语言翻译器C.一般来说我在某种程度上完成了它,但我发现自己并不理解一些重要的事情才能完成它。

首先,我似乎无法理解以下语法规则是如何工作的

  

声明列表→声明列表声明

     

local-declarations→local-declarations declaration

我在{语句声明“上看到了How do i implement If statement in Flex/bison的示例,引用:

struct AstElement* makeStatement(struct AstElement* result, struct  AstElement* toAppend)
{
if(!result)
{
    result = checkAlloc(sizeof(*result));
    result->kind = ekStatements;
    result->data.statements.count = 0;
    result->data.statements.statements = 0;
}
assert(ekStatements == result->kind);
result->data.statements.count++;
result->data.statements.statements = realloc(result->data.statements.statements, result->data.statements.count*sizeof(*result->data.statements.statements));
result->data.statements.statements[result->data.statements.count-1] = toAppend;
return result;
}

但我不知道其他规则是否也是一样的,而且,我想了解我在做什么,而不仅仅是复制。

我的第二个问题是以下语法规则

  

声明→type-spec id; | type-spec id [num];

     

type-specifier→int

我在这里得到了重点,它是什么,它应该做什么等但我不能将我的理解转换为代码和C.

1 个答案:

答案 0 :(得分:2)

在Yacc中,您可以为解析器遇到的任何规则提供代码,并且该代码(通常)从派生的父规则中提供一个值,最后该值是转换后的程序。对于你的第二个例子:

  

声明→type-spec id; | type-spec id [num];

     

type-specifier→int

第二条规则应该返回一些内容来识别遇到的int类型;这可能是字符串本身或该类型的一些内部标识符。所以它应该是这样的:

type-specifier → int { $$ = $1 };

表示type-specifier的值是词法分析器为令牌int发送的内容。

然后假设它是从另一个规则派生出来的,那个显然是用于声明一个简单变量或数组的东西,那么yacc规则可能是这样的:

declaration → type-spec id         { addSymbol($1,$2); } ;
            | type-spec id [ num ] { addSymbolForArray($1,$2,$3); };

其中两个函数分别为符号表的内部表示添加一个新符号,带有类型(如果需要在符号表中某处编码类型),标识符和数组中的数组大小

同样适用于任何规则,但有时规则几乎没有,因为(可能)你的:

  

声明列表→声明列表声明

因为声明已在 declaration派生规则中解决

请记住,这是一个简单的建议,可以让您更清楚,有很多事情需要注意。但原则是:问自己,解析规则时你必须做什么,它对你的语义意味着什么?