2016-09-04 94 views
-2

我一直在尝试编写一种语言翻译器,使用flex和yacc与C.通常我以某种方式完成它,但我发现自己不理解一些重要的事情以完成它。yacc语法规则的语义

所有我似乎无法理解下面的语法规则是如何工作的

声明列表→申报表声明

本地报关→本地报关申报的第一

我在这里看到一个例子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 [num];

类型说明符→INT

我在这里获得了整点,它是什么,它应该做什么等等,但我无法将认识转化为代码和C

+1

您应该编写代码,以便在您的程序符合规则时执行任​​何操作。 – immibis

+0

嗯,我知道这很多。我觉得我需要的代码是特定的,但是。 – codeNewbie

+0

当程序符合规则时,您希望程序执行什么操作? – immibis

回答

2

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

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

类型说明符→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派生规则。

请记住,这是一个简单的建议,让事情变得更加清晰,有很多事情需要关注。但是原则就在那里:问问自己,当规则被解析时你需要做什么,它对你的语义意味着什么?

+0

非常感谢您的回答。它确实为我提供了一些更清晰的东西。如果您有一些时间,请查看我对我的问题的最新评论。我试图弄清楚是否应该将类似于代码,因为这些项目非常相似。 – codeNewbie