Bison, Flex和编译器错误解决:parser.y

3

我在编译我的编译器时遇到了错误,但我不知道为什么。我正在运行OS X 10.9.1和最新的Xcode。

parser.y:1.1-5: 无效指令:`%code' parser.y:1.7-9: 语法错误,意外的标识符

这是我的parser.y代码:

%code top {

#include "frontend.h"
#include "type.h"
#include "ast.h"
#include "env.h"
#include <glib.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>

extern int yylex(void);
extern int yyerror(const char*);

}

%code requires {

#include "type.h"
#include "ast.h"
#include <glib.h>

}

%union {
      char* id;
      char* str;
      int num;
      GList* list;
      Type* type;
      struct exp* exp;
      struct decl* decl;
      struct stmt *stmt;
      struct GList *stmts_list;
};

%type <exp> exp
%type <exp> aexp
%type <exp> bexp
%type <exp> obj_lit
%type <exp> lvalue
%type <exp> fun_call

%type <list> decls
%type <list> var_decls
%type <decl> decl
%type <decl> var_decl
%type <decl> fun_decl
%type <decl> type_decl
%type <type> type


/* Ids could be types or exps. */
%token <id> T_ID
%token <str> T_STR
%token <num> T_NUM

%token T_LT_EQ "<="
%token T_GT_EQ ">="
%token T_EQ "=="
%token T_NOT_EQ "!="

%token T_VAR T_TYPE T_FUNCTION
      T_FOR T_TO T_WHILE T_IF T_ELSE T_RETURN
      T_NIL T_TRUE T_FALSE
      T_INT T_BOOL
      T_UNKNOWN

%left '|'
%left '&'
%left "==" "!="
%left '<' '>' "<=" ">="
%left '+' '-'
%left '*' '/' '%'
%left T_UMINUS T_UPLUS '!'

%start program

%%

// ian start

program:
      decls {
            done_parsing($1);
      }

decls:
      { GList* declsList = NULL; $$ = declsList; }
    | decls decl {
            $$ = g_list_append($1, $2);
      }

decl: var_decl {
            $$ = $1;
      }
      | fun_decl {
            $$ = $1;
      }
      | type_decl {
            $$ = $1;
      }

var_decls: 
      { GList* declsList = NULL; $$ = declsList; } | var_decls var_decl {
            $$ = g_list_append($1, $2);
      }

var_decl: 
      T_VAR T_ID ':' type ';' {
            Symbol varName = symbol_var($2);
            $$ = decl_new(varName, $4, NULL, NULL, NULL);
      }
      | T_VAR T_ID ':' type '=' exp ';' {
            Symbol varName = symbol_var($2);
            $$ = decl_new(varName, $4, $6, NULL, NULL);
      }

type_decl: 
      T_TYPE T_ID ':' type ';' {
            Symbol typeName = symbol_typename($2);
            $$ = decl_new(typeName, $4, NULL, NULL, NULL);
      }

// ian end

// adam start

param_decl: 
      T_ID ':' type

param_decls: 
      param_decl
      | param_decls ',' param_decl

field_decl: 
      T_ID ':' type

field_decls: 
      field_decl
      | field_decls ',' field_decl

type: 
      T_INT
      | T_BOOL
      | T_ID
      | '[' type ']'
      | '{' field_decls '}'

fun_decl: 
      T_FUNCTION T_ID '(' param_decls ')' ':' type '{' var_decls stmts '}'
      | T_FUNCTION T_ID '(' param_decls ')' '{' var_decls stmts '}'
      | T_FUNCTION T_ID '(' ')' ':' type '{' var_decls stmts '}'
      | T_FUNCTION T_ID '(' ')' '{' var_decls stmts '}'

// adam end

// vv IAN
exp:
      aexp {
            $$ = $1;
      }
      | bexp {
            $$ = $1;
      }
      | obj_lit {
            $$ = $1;
      }
      | fun_call {
            $$ = $1;
      }
      | lvalue {
            $$ = $1;
      }
      | '(' exp ')' {
            $$ = $2;
      }

aexp: 
      T_NUM {
            exp_num_new($1);
      }
      | '+' exp %prec T_UPLUS {
            $$ = exp_binop_new(AST_EXP_MUL, exp_num_new(1), $2);
      }
      | '-' exp %prec T_UMINUS {
            $$ = exp_binop_new(AST_EXP_MUL, exp_num_new(-1), $2);
      }
      | exp '+' exp {
            $$ = exp_binop_new(AST_EXP_PLUS, $1, $3);
      }
      | exp '-' exp {
            $$ = exp_binop_new(AST_EXP_MINUS, $1, $3);
      }
      | exp '/' exp {
            $$ = exp_binop_new(AST_EXP_DIV, $1, $3);
      }
      | exp '%' exp {
            $$ = exp_binop_new(AST_EXP_MOD, $1, $3);
      }
      | exp '*' exp {
            $$ = exp_binop_new(AST_EXP_MUL, $1, $3);
      }

bexp: 
      T_TRUE {
            $$ = exp_new(AST_EXP_TRUE);
      }
      | T_FALSE {
            $$ = exp_new(AST_EXP_FALSE);
      }
      | '!' exp {
            $$ = exp_not_new($2);
      }
      | exp '|' exp {
            $$ = exp_binop_new(AST_EXP_OR, $1, $3);
      }
      | exp '&' exp {
            $$ = exp_binop_new(AST_EXP_AND, $1, $3);
      }
      | exp '<' exp {
            $$ = exp_binop_new(AST_EXP_LT, $1, $3);
      }
      | exp "<=" exp {
            $$ = exp_binop_new(AST_EXP_LT_EQ, $1, $3);
      }
      | exp '>' exp {
            $$ = exp_binop_new(AST_EXP_GT, $1, $3);
      }
      | exp ">=" exp {
            $$ = exp_binop_new(AST_EXP_GT_EQ, $1, $3);
      }
      | exp "==" exp {
            $$ = exp_binop_new(AST_EXP_EQ, $1, $3);
      }
      | exp "!=" exp {
            $$ = exp_binop_new(AST_EXP_NOT_EQ, $1, $3);
      }

// jon start

obj_lit: array_lit | struct_lit
      | T_NIL

array_lit:
      '[' exps ']'
      | T_STR

exps: 
      exp
      | exps ',' exp

struct_lit:
      '{' field_inits '}'

field_init: 
      T_ID '=' exp

field_inits: 
      field_init
      | field_inits ',' field_init

fun_call:
      T_ID '(' exps ')'
      | T_ID '(' ')'

lvalue: 
      T_ID
      | struct_exp '.' T_ID
      | array_exp '[' exp ']'

array_exp: array_lit | fun_call | lvalue
struct_exp: struct_lit | fun_call | lvalue

// jon end

// patrick start

stmts:               { GList *stmts_list = NULL; stmts_list = $$; }
        | stmts stmt { $$ = g_list_append($1, $2); }

stmt:
    exp ';' { $$ = stmt_exp_new($2); }
    | lvalue '=' exp ';' { $$ = stmt_assign_new($1 , $3); }
    | T_IF '(' exp ')' block T_ELSE block { $$ = stmt_if_new($3, $5, $7); }
    | T_IF '(' exp ')' block { $$ = stmt_if_new($3, $5, NULL); }
    | T_WHILE '(' exp ')' block { $$ = stmt_while_new($3, $5); }
    | T_FOR '(' lvalue '=' exp T_TO exp ')' block { $$ = stmt_for_new($3, $5, $7, $9); }
    | T_RETURN '(' exp ')' ';' { $$ = stmt_return_new($3); }
    | T_RETURN ';' { $$ = stmt_return_new(NULL); }

block:
    '{' stmts '}' { $$ = $2; }

//patrick end

%%

int yyerror(const char *p) {
      fprintf(stderr, "Error: %s\n", p);
      return 0;
}

2
你使用的是哪个 Bison 版本? - rici
3
OP可能拥有的是Bison 2.3版版权,日期为2006年(无论如何,在我的Mac OS X 10.9.2上都是这样)。 - Jonathan Leffler
也许 OP 真的得到了某个版本的 byacc(苹果对 GPL 有过敏反应...) - vonbrand
@JonathanLeffler:苹果公司是否相信将旧的、陈旧的手册与其陈旧的软件一起分发呢? :) 如果是这样,也许应该将MacOSX用户引导到适当的文档... - rici
@rici:在某些情况下(如Bash 3.x与4.x),我认为差异是由于GPL从v2到v3的变化所致;我听说过苹果不愿使用GPL v3代码。请适当保留这种说法。 - Jonathan Leffler
1个回答

6
从评论中看,你使用的bison版本可能不支持%code指令。我认为该指令的初始形式直到bison 2.3b版本才得以实现,而更高级的形式(%code top)则是在2007年某个时候引入的。(这是通过查看变更日志获得的信息,而不是代码历史记录。)
如果是这种情况,你有两个选择:
  1. 只需使用%{...%}。我在你的源文件中没有看到任何明显的原因,你需要首先使用%code top。(或者你为什么要两次包含自己的头文件)
  2. 下载并编译与你正在阅读的手册更相符的bison版本。
当然,这两种方法并不是互斥的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接