2011-03-09 66 views
1

我使用Flex /野牛一個新手,並試圖實現我的語法/詞法分析器的第一步......Flex/Bison ...小查詢?

在我的「tokens.l」文件我這樣做,以確定一個「關鍵詞」:

"surface" return (yylval.token=TSURFACESHADER); 

在我parser.y文件我下面的聲明TSURFACESHADER:

%token <int> TSURFACESHADER 

但是我編譯時有以下錯誤:

error C2065: 'TSURFACESHADER' : undeclared identifier 

你對這個問題有什麼想法嗎?另外,在解析器生成過程中出現了一些錯誤,並且在使用它時,無法「發現」用「表面」關鍵字描述的「着色器」!它告訴我,我的着色器是一個功能!

例如,這裏是一個小的代碼來解析(着色器):

surface matte(float Kd, float Cs) { int x = Kd * 5 + 3 } 

THX對您有所幫助

我也加入我.L這裏.Y文件

tokens.l文件

/* Option 'noyywrap' indicates that when EOF is hit, yyin does not automatically reset to another file. */ 
%option noyywrap 

%{ 
#include <string> 
#include "node.h" 
#include "parser.hpp" 
#define SAVE_TOKEN yylval.string = new std::string(yytext, yyleng) 
#define TOKEN(t) (yylval.token = t) 
#define YY_NEVER_INTERACTIVE 1 
//extern "C" int yywrap() { } 
%} 

%% 

[ \t\n]     ; 
"surface"    return (yylval.token=TSURFACESHADER); 
[a-zA-Z_][a-zA-Z0-9_]* SAVE_TOKEN; return TIDENTIFIER; 
[0-9]+\.[0-9]*   SAVE_TOKEN; return TDOUBLE; 
[0-9]+     SAVE_TOKEN; return TINTEGER; 
"="      return TOKEN(TEQUAL); 
"=="     return TOKEN(TCEQ); 
"!="     return TOKEN(TCNE); 
"<"      return TOKEN(TCLT); 
"<="     return TOKEN(TCLE); 
">"      return TOKEN(TCGT); 
">="     return TOKEN(TCGE); 
"("      return TOKEN(TLPAREN); 
")"      return TOKEN(TRPAREN); 
"{"      return TOKEN(TLBRACE); 
"}"      return TOKEN(TRBRACE); 
"."      return TOKEN(TDOT); 
","      return TOKEN(TCOMMA); 
"+"      return TOKEN(TPLUS); 
"-"      return TOKEN(TMINUS); 
"*"      return TOKEN(TMUL); 
"/"      return TOKEN(TDIV); 
.      printf("Unknown token!\n"); yyterminate(); 

%% 

而parser.y文件

%{ 
    #include "node.h" 
    NBlock *programBlock; /* the top level root node of our final AST */ 

    extern int yylex(); 
    void yyerror(const char *s) { printf("ERROR: %s\n", s); } 
%} 

/* Represents the many different ways we can access our data */ 
%union { 
    Node *node; 
    NBlock *block; 
    NExpression *expr; 
    NStatement *stmt; 
    NIdentifier *ident; 
    NVariableDeclaration *var_decl; 
    std::vector<NVariableDeclaration*> *varvec; 
    std::vector<NExpression*> *exprvec; 
    std::string *string; 
    int token; 
} 

/* Define our terminal symbols (tokens). This should match our tokens.l lex file. We also define the node type they represent. */ 
%token <string> TIDENTIFIER TINTEGER TDOUBLE 
%token <token> TCEQ TCNE TCLT TCLE TCGT TCGE TEQUAL 
%token <token> TLPAREN TRPAREN TLBRACE TRBRACE TCOMMA TDOT 
%token <token> TPLUS TMINUS TMUL TDIV 
%token <int> TSURFACESHADER 

/* Define the type of node our nonterminal symbols represent. 
    The types refer to the %union declaration above. Ex: when 
    we call an ident (defined by union type ident) we are really 
    calling an (NIdentifier*). It makes the compiler happy. 
*/ 
%type <ident> ident 
/* %type <ident> shadertype */ 
%type <expr> numeric expr 
%type <varvec> func_decl_args 
%type <varvec> shader_decl_args 
%type <exprvec> call_args 
%type <block> program stmts block 
%type <stmt> stmt var_decl func_decl shader_decl 
%type <token> comparison 

/* Operator precedence for mathematical operators */ 
%left TPLUS TMINUS 
%left TMUL TDIV 

%start program 

%% 

program : stmts { programBlock = $1; } 
     ; 

stmts : stmt { $$ = new NBlock(); $$->statements.push_back($<stmt>1); } 
     | stmts stmt { $1->statements.push_back($<stmt>2); } 
     ; 

stmt : var_decl | func_decl | shader_decl 
    | expr { $$ = new NExpressionStatement(*$1); } 
    ; 

block : TLBRACE stmts TRBRACE { $$ = $2; } 
     | TLBRACE TRBRACE { $$ = new NBlock(); } 
     ; 

var_decl : ident ident { $$ = new NVariableDeclaration(*$1, *$2); } 
     | ident ident TEQUAL expr { $$ = new NVariableDeclaration(*$1, *$2, $4); } 
     ; 

shader_decl : TSURFACESHADER ident TLPAREN shader_decl_args TRPAREN block 
      { $$ = new NShaderDeclaration(*$2, *$4, *$6); delete $4; } 
      ; 

shader_decl_args : /*blank*/ { $$ = new VariableList(); } 
      | var_decl { $$ = new VariableList(); $$->push_back($<var_decl>1); } 
      | shader_decl_args TCOMMA var_decl { $1->push_back($<var_decl>3); } 
      ; 

func_decl : ident ident TLPAREN func_decl_args TRPAREN block 
      { $$ = new NFunctionDeclaration(*$1, *$2, *$4, *$6); delete $4; } 
      ; 

func_decl_args : /*blank*/ { $$ = new VariableList(); } 
      | var_decl { $$ = new VariableList(); $$->push_back($<var_decl>1); } 
      | func_decl_args TCOMMA var_decl { $1->push_back($<var_decl>3); } 
      ; 

ident : TIDENTIFIER { $$ = new NIdentifier(*$1); delete $1; } 
     ; 

numeric : TINTEGER { $$ = new NInteger(atol($1->c_str())); delete $1; } 
     | TDOUBLE { $$ = new NDouble(atof($1->c_str())); delete $1; } 
     ; 

expr : ident TEQUAL expr { $$ = new NAssignment(*$<ident>1, *$3); } 
    | ident TLPAREN call_args TRPAREN { $$ = new NMethodCall(*$1, *$3); delete $3; } 
    | ident { $<ident>$ = $1; } 
    | numeric 
    | expr comparison expr { $$ = new NBinaryOperator(*$1, $2, *$3); } 
    | TLPAREN expr TRPAREN { $$ = $2; } 
    ; 

call_args : /*blank*/ { $$ = new ExpressionList(); } 
      | expr { $$ = new ExpressionList(); $$->push_back($1); } 
      | call_args TCOMMA expr { $1->push_back($3); } 
      ; 

comparison : TCEQ | TCNE | TCLT | TCLE | TCGT | TCGE 
      | TPLUS | TMINUS | TMUL | TDIV 
      ; 

%% 

回答

2

你需要有行#include "parser.tab.h"在tokens.l文件與令牌定義的頭文件野牛生成當你bison -d parser.y

調用它拉

你有一個#include "parser.hpp"行,但它不清楚parser.hpp是什麼或它來自哪裏 - 你可能會嘗試將parser.tab.h重命名爲parser.hpp,並且出錯了。