Flex / Bison ... небольшой запрос? - PullRequest
1 голос
/ 09 марта 2011

Я новичок в 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 }

Спасибо за вашу помощь

Я также присоединяюсь к своим файлам .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
           ;

%%

1 Ответ

2 голосов
/ 09 марта 2011

Вам нужно иметь строку #include "parser.tab.h" в вашем файле tokens.l, чтобы получить заголовочный файл с определениями токенов, которые генерирует bison, когда вы вызываете его с помощью bison -d parser.y

У вас есть #include "parser.hpp" line, но не ясно, что такое parser.hpp или откуда он взялся - вы можете пытаться переименовать parser.tab.h в parser.hpp, и это как-то не так.

...