3
votes

hallo, i have a problem, the followed program gives back an error, error:: Undeclared(first use in function), why this error appears all tokens are declared, but this error comes, can anyone help me, here are the lex and yac files.thanks

lex:

%{
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

2 Answers

4
votes

Your primary problem is that you're trying to include your lexer into your parser. What you (at least normally) want to do is have yacc (bison, if you must) produce a header (y.tab.h), by using yacc -d, and include that in your lexer.

Start of lexer:

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

Since your parser refers to the variables defined above, you'll then declare than in your parser source file:

extern int yylinenu;
extern int yycolno;

Your main() and error() were also a bit of a mess (your main() looks like you were probably playing around trying to figure out what was going on...).

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

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

Other than that, your grammar has a minor detail or two that I'm pretty sure aren't quite what you really intended. For example:

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

Presumably, where you've matched a "while" you want to print out "while", not "printf":

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

Likewise, in:

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

I'd guess you probably want to print out an 'if' at the beginning of each:

|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");}

As a final note, I'd suggest some indentation and blank lines, so your grammar rules would be laid out something like this:

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");}
    ;

Of course, you can vary that, such as putting the actions on separate lines (especially if they're long), but the general idea remains the same. You shouldn't really need comments to tell where one rule ends and another starts -- formatting can make that apparent.

Edit: I forgot to mention one other point: with a bottom-up parser (like bison/yacc/byacc generate) left recursion is generally preferred to right recursion, so you'd generally prefer to change this:

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

To:

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

Here is the example, the JMP instruction goes to the label L1.

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

thanks.