Сгибание / бизон, ошибка: необъявленная - PullRequest
3 голосов
/ 19 апреля 2010

алло, у меня есть проблема, следующая программа возвращает ошибку error :: Undeclared (первое использование в функции), почему эта ошибка появляется, все токены объявлены, но эта ошибка появляется, может кто-нибудь мне помочь, вот файлы lex и yac .THANKS

Лекс:

%{
int yylinenu= 1;
int yycolno= 1;
%}

%x STR
DIGIT                     [0-9]
ALPHA                     [a-zA-Z]
ID                        {ALPHA}(_?({ALPHA}|{DIGIT}))*_?
GROUPED_NUMBER        ({DIGIT}{1,3})(\.{DIGIT}{3})*
SIMPLE_NUMBER             {DIGIT}+
NUMMER                {GROUPED_NUMBER}|{SIMPLE_NUMBER}
%%
<INITIAL>{
[\n]                      {++yylinenu ; yycolno=1;} 
[ ]+                      {yycolno=yycolno+yyleng;} 
[\t]+             {yycolno=yycolno+(yyleng*8);} 
"*"                       {return MAL;}
"+"                       {return PLUS;}
"-"                       {return MINUS;}
"/"                       {return SLASH;}
"("                       {return LINKEKLAMMER;}
")"                       {return RECHTEKLAMMER;}
"{"                       {return LINKEGESCHWEIFTEKLAMMER;}
"}"                       {return RECHTEGESCHEIFTEKLAMMER;}
"="                       {return GLEICH;}
"=="                      {return GLEICHVERGLEICH;}
"!="                      {return UNGLEICH;}
"<"                       {return KLEINER;}
">"                       {return GROSSER;}
"<="                      {return KLEINERGLEICH;}
">="                      {return GROSSERGLEICH;}
"while"                   {return WHILE;}
"if"                      {return IF;}
"else"                    {return ELSE;}
"printf"                  {return PRINTF;}
";"                       {return SEMIKOLON;}  
\/\/[^\n]*                { ;}
{NUMMER}                  {return NUMBER;}
{ID}                      {return IDENTIFIER;}
\"                {BEGIN(STR);}                  
.                         {;} 
}

<STR>{ 
\n                        {++yylinenu ;yycolno=1;} 
([^\"\\]|"\\t"|"\\n"|"\\r"|"\\b"|"\\\"")+        {return STRING;}
\"                                             {BEGIN(INITIAL);}
}
%%
yywrap()
{
}

YACC:

%{
#include stdio.h>
#include string.h>
#include "lex.yy.c"

void yyerror(char *err);
int error=0,linecnt=1;
%}

%token IDENTIFIER NUMBER STRING COMMENT PLUS MINUS MAL SLASH LINKEKLAMMER RECHTEKLAMMER LINKEGESCHWEIFTEKLAMMER RECHTEGESCHEIFTEKLAMMER GLEICH GLEICHVERGLEICH UNGLEICH GROSSER KLEINER GROSSERGLEICH KLEINERGLEICH IF ELSE WHILE PRINTF SEMIKOLON


%start Stmts

%%
Stmts : Stmt
{puts("\t\tStmts : Stmt");}
|Stmt Stmts
{puts("\t\tStmts : Stmt Stmts");}
; //NEUE REGEL----------------------------------------------
Stmt : LINKEGESCHWEIFTEKLAMMER Stmts RECHTEGESCHEIFTEKLAMMER
{puts("\t\tStmt : '{' Stmts '}'");}
|IF LINKEKLAMMER Cond RECHTEKLAMMER Stmt
{puts("\t\tStmt : '(' Cond ')' Stmt");}
|IF LINKEKLAMMER Cond RECHTEKLAMMER Stmt  ELSE Stmt
{puts("\t\tStmt : '(' Cond ')' Stmt 'ELSE' Stmt");}
|WHILE LINKEKLAMMER Cond RECHTEKLAMMER Stmt
{puts("\t\tStmt : 'PRINTF' Expr ';'");}
|PRINTF Expr SEMIKOLON
{puts("\t\tStmt : 'PRINTF' Expr ';'");}
|IDENTIFIER GLEICH Expr SEMIKOLON
{puts("\t\tStmt : 'IDENTIFIER' '=' Expr ';'");}
|SEMIKOLON
{puts("\t\tStmt : ';'");}
;//NEUE REGEL ---------------------------------------------
Cond: Expr GLEICHVERGLEICH Expr 
{puts("\t\tCond : '==' Expr");}
|Expr UNGLEICH Expr
{puts("\t\tCond : '!=' Expr");}
|Expr KLEINER Expr
{puts("\t\tCond : '<' Expr");}
|Expr KLEINERGLEICH Expr
{puts("\t\tCond : '<=' Expr");}
|Expr GROSSER Expr
{puts("\t\tCond : '>' Expr");}
|Expr GROSSERGLEICH Expr
{puts("\t\tCond : '>=' Expr");}
;//NEUE REGEL --------------------------------------------
Expr:Term 
{puts("\t\tExpr : Term");}
|Term PLUS Expr 
{puts("\t\tExpr : Term '+' Expr");}
|Term MINUS Expr 
{puts("\t\tExpr : Term '-' Expr");}
;//NEUE REGEL --------------------------------------------
Term:Factor
{puts("\t\tTerm : Factor");}
|Factor MAL Term
{puts("\t\tTerm : Factor '*' Term");}
|Factor SLASH Term
{puts("\t\tTerm : Factor '/' Term");}
;//NEUE REGEL --------------------------------------------
Factor:SimpleExpr
{puts("\t\tFactor : SimpleExpr");}
|MINUS SimpleExpr
{puts("\t\tFactor : '-' SimpleExpr");}
;//NEUE REGEL --------------------------------------------
SimpleExpr:LINKEKLAMMER Expr RECHTEKLAMMER
{puts("\t\tSimpleExpr : '(' Expr ')'");}
|IDENTIFIER
{puts("\t\tSimpleExpr : 'IDENTIFIER'");}
|NUMBER 
{puts("\t\tSimpleExpr : 'NUMBER'");}
|STRING
{puts("\t\tSimpleExpr : 'String'");}
;//ENDE -------------------------------------------------
%%
void yyerror(char *msg)
{
 error=1;
 printf("Line: %d , Column: %d : %s \n", yylinenu, yycolno,yytext, msg); 
}
int main(int argc, char *argv[])
{

        int val;
        while(yylex())  
        {       
         printf("\n",yytext);       
    }
    return yyparse();
}

Ответы [ 2 ]

3 голосов
/ 20 апреля 2010

Ваша основная проблема в том, что вы пытаетесь включить свой лексер в свой парсер. То, что вы (по крайней мере, обычно) хотите сделать, - это чтобы yacc (bison, если вам нужно) генерировал заголовок (y.tab.h), используя yacc -d, и включал его в свой лексер.

Начало лексера:

%{
#include "y.tab.h"
int yylinenu= 1;
int yycolno= 1;
%}
// ...

Поскольку ваш синтаксический анализатор ссылается на переменные, определенные выше, вы затем объявите, чем в исходном файле вашего синтаксического анализатора:

extern int yylinenu;
extern int yycolno;

Ваши main() и error() также были немного беспорядочными (ваш main() выглядит так, как будто вы, вероятно, играли, пытаясь выяснить, что происходит ...).

void yyerror(char *msg)
{
    printf("Line: %d , Column: %d : %s \n", yylinenu, yycolno, msg); 
}

int main(int argc, char *argv[])
{
    return yyparse();
}

Кроме этого, в вашей грамматике есть мелкая деталь или две, которые, я уверен, не совсем то, что вы действительно хотели. Например:

|WHILE LINKEKLAMMER Cond RECHTEKLAMMER Stmt 
    {puts("\t\tStmt : 'PRINTF' Expr ';'");}
|PRINTF Expr SEMIKOLON  
    {puts("\t\tStmt : 'PRINTF' Expr ';'");}

Предположительно, когда вы выбрали "while", которое хотите распечатать "while", а не "printf":

|WHILE LINKEKLAMMER Cond RECHTEKLAMMER Stmt 
    {puts("\t\tStmt : 'WHILE' Expr ';'");}

Аналогично, в:

|IF LINKEKLAMMER Cond RECHTEKLAMMER Stmt    
    {puts("\t\tStmt : '(' Cond ')' Stmt");}
|IF LINKEKLAMMER Cond RECHTEKLAMMER Stmt  ELSE Stmt 
    {puts("\t\tStmt : '(' Cond ')' Stmt 'ELSE' Stmt");}

Полагаю, вы, возможно, захотите распечатать в начале каждого слова "если":

|IF LINKEKLAMMER Cond RECHTEKLAMMER Stmt    
    {puts("\t\tStmt : 'IF' '(' Cond ')' Stmt");}
|IF LINKEKLAMMER Cond RECHTEKLAMMER Stmt  ELSE Stmt 
    {puts("\t\tStmt : 'IF' '(' Cond ')' Stmt 'ELSE' Stmt");}

В качестве заключительного замечания я бы предложил некоторые отступы и пустые строки, чтобы ваши правила грамматики были изложены примерно так:

Term:Factor                 {puts("\t\tTerm : Factor");}
    | Factor MAL Term       {puts("\t\tTerm : Factor '*' Term");}
    | Factor SLASH Term     {puts("\t\tTerm : Factor '/' Term");}
    ;

Factor:SimpleExpr           {puts("\t\tFactor : SimpleExpr");}
    | MINUS SimpleExpr      {puts("\t\tFactor : '-' SimpleExpr");}
    ;

Конечно, вы можете изменять это, например, помещать действия в отдельные строки (особенно если они длинные), но общая идея остается прежней. Вы не должны действительно нуждаться в комментариях, чтобы сказать, где заканчивается одно правило и начинается другое - форматирование может сделать это очевидным.

Редактировать: я забыл упомянуть еще один момент: при использовании синтаксического анализатора снизу вверх (например, bison / yacc / byacc generate) рекурсия слева предпочтительнее, чем рекурсия вправо, поэтому вы обычно предпочитаете изменить это:

Stmts : Stmt                {puts("\t\tStmts : Stmt");}
    | Stmt Stmts            {puts("\t\tStmts : Stmt Stmts");}
    ;

Кому:

Stmts : Stmt                {puts("\t\tStmts : Stmt");}
    | Stmts Stmt            {puts("\t\tStmts : Stmts Stmt");}
    ;
0 голосов
/ 26 апреля 2010

Вот пример, инструкция JMP идет на метку L1.

:L1
IF FLAG AND X"0001"
EVT 23;
ELSE
WAIT 500 ms;
JMP L1;
END IF;

спасибо.

...