这个程序语法只识别名称为'ID'的变量吗?

问题描述:

我需要在lex/flex中创建一个扫描器,以在yacc/bison中查找令牌和解析器,以基于以下语法处理这些令牌。当我在制作扫描仪的过程中,在我看来,这种语言的变量,函数和数组只能有'ID'这个名字。我误读了这个yacc文件吗?这个程序语法只识别名称为'ID'的变量吗?

/* C-Minus BNF Grammar */ 

%token ELSE 
%token IF 
%token INT 
%token RETURN 
%token VOID 
%token WHILE 

%token ID 
%token NUM 

%token LTE 
%token GTE 
%token EQUAL 
%token NOTEQUAL 
%% 

program : declaration_list ; 

declaration_list : declaration_list declaration | declaration ; 

declaration : var_declaration | fun_declaration ; 

var_declaration : type_specifier ID ';' 
       | type_specifier ID '[' NUM ']' ';' ; 

type_specifier : INT | VOID ; 

fun_declaration : type_specifier ID '(' params ')' compound_stmt ; 

params : param_list | VOID ; 

param_list : param_list ',' param 
      | param ; 

param : type_specifier ID | type_specifier ID '[' ']' ; 

compound_stmt : '{' local_declarations statement_list '}' ; 

local_declarations : local_declarations var_declaration 
        | /* empty */ ; 

statement_list : statement_list statement 
       | /* empty */ ; 

statement : expression_stmt 
      | compound_stmt 
      | selection_stmt 
      | iteration_stmt 
      | return_stmt ; 

expression_stmt : expression ';' 
       | ';' ; 

selection_stmt : IF '(' expression ')' statement 
       | IF '(' expression ')' statement ELSE statement ; 

iteration_stmt : WHILE '(' expression ')' statement ; 

return_stmt : RETURN ';' | RETURN expression ';' ; 

expression : var '=' expression | simple_expression ; 

var : ID | ID '[' expression ']' ; 

simple_expression : additive_expression relop additive_expression 
        | additive_expression ; 

relop : LTE | '<' | '>' | GTE | EQUAL | NOTEQUAL ; 

additive_expression : additive_expression addop term | term ; 

addop : '+' | '-' ; 

term : term mulop factor | factor ; 

mulop : '*' | '/' ; 

factor : '(' expression ')' | var | call | NUM ; 

call : ID '(' args ')' ; 

args : arg_list | /* empty */ ; 

arg_list : arg_list ',' expression | expression ; 

ID只是词法分析器返回的终端类型。这个想法是,在变量名称(和数字)的情况下,其他返回的信息将指定名称(或数字)。在C状伪代码,词法分析器是做这样的:

char *tok = tokenise(); 
if (!strcmp(tok, "int")) 
{ 
    return INT; 
} 
else if (is_name(tok)) 
{ 
    strcpy(parser.name, tok); 
    return ID; 
} 
else if (is_number(tok)) 
{ 
    parser.number = atoi(tok); 
    return NUM; 
} 
... 

解析器接收到终端类型(INT,ID,NUM,等),这是足够的信息用于其应用语法规则。然后,规则中的操作可以直接或在构建AST时包含额外的信息(parser.name,parser.number等)。

+0

你怎么知道INT是字面上的,而不是ID? – neuromancer 2009-11-17 07:20:52

+0

这是一个非常好的问题。从语法中无法辨别。我猜根据你的语法与其他几个我用他们的伴随词法分析器看到的语法极其相似。虽然你的问题似乎是“如何在真实世界中工作(用现实的词法分析器)?”我认为我的假设是合理的。 – Edmund 2009-11-17 07:52:18