views:

148

answers:

2

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();
}
+1  A: 

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");}
    ;
Jerry Coffin
hallo Jerry,i have an error, when i ompile gcc -o lex.yy.c then the error undefined reference to yylex appears, can you help me out thanks.
Imran
hallo jerry,can help me please, this program dont function, i dont understand why, can you try if this function by you, i' very grateful to youthanks.
Imran
About all I guess is that you're building out of order. The normal (though counterintuitive)sequence is first the parser (yacc -d xxx.y) then the lexer (flex yyy.l) then compile (gcc y.tab.c lex.yy.c).
Jerry Coffin
Hallo jerry, i wanted to aski want to implement a Jump instruction, to jump to defined labels, i found out that it could be implemented with a function goto of flex/bison, but i hav no really idea how to do, can you help me out.thanks.i show you an example how it looks like.
Imran
It's almost impossible to answer without knowing something about your implementation in general. If you're doing something compiler-like, a goto in the source code will usually translate to a branch or jump instruction in the object code. I'm less certain with an interpreter -- I haven't done much in the way of pure interpreters with lex/yacc (or similar tools).
Jerry Coffin
what i ment was, its allround a syntactical analysis and i want that the compiler i build should recognise the JMP Instructor, when i give an Input like at the top, and gives me back, that JMP was used und it jumped to the label L1, so i implementet with goto if this runs then i will change it to JMP, you can look out the code in the Question How do i implement if statement in Flex/Bison the second code from the top.thanks.
Imran
hallo,i found out, that ihave to make a table where the commands like JMP are and when a input comes with JMP it has to search after JMP and give it out. JMP must be funktion that jumps to a label, which is defined., have you any idea how i make this table, or how to search after commands given in the input thanks.
Imran
A: 

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.

Imran