2009-11-17 9 views
0

Je dois faire un scanner dans lex/flex pour trouver des jetons et un analyseur dans yacc/bison pour traiter ces jetons basés sur la grammaire suivante. Quand j'étais en train de faire le scanner, il m'a semblé que les variables, les fonctions et les tableaux dans cette langue ne pouvaient avoir que le nom 'ID'. Suis-je mal interpréter ce fichier yacc?Est-ce que cette grammaire de programme reconnaît seulement les variables avec le nom '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 ; 

Répondre

1

ID est juste le type de terminal retourné par le lexer. L'idée est que, dans le cas de noms de variables (et de nombres), d'autres informations renvoyées spécifieront le nom (ou le numéro). Dans psuedo code C comme, le lexer fait quelque chose comme:

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; 
} 
... 

L'analyseur reçoit le type de terminal (INT, ID, NUM, etc.) et cette information est suffisante pour appliquer les règles de grammaire . Les actions dans les règles peuvent alors inclure les informations supplémentaires (parser.name, parser.number, etc.) directement ou lors de la construction de l'AST.

+0

Comment pouvez-vous dire que INT est pris littéralement, mais pas ID? – neuromancer

+0

C'est une très bonne question. Il n'y a aucun moyen de dire de la grammaire. Je devinais sur la base de l'extrême similitude de votre grammaire à plusieurs autres que j'ai vu avec leurs lexers d'accompagnement. Bien que votre question semble être "comment cela fonctionnerait-il dans le monde réel (avec un lexer réaliste)?" Je pense que mon hypothèse est raisonnable. – Edmund

Questions connexes