3

ハロー、私は問題があります、次のプログラムはエラーを返します、エラー::宣言されていません(関数での最初の使用)、なぜこのエラーが表示されるのかすべてのトークンが宣言されていますが、このエラーが発生します、誰もが私を助けることができます、ここにlexとyacfiles.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();
}
4

2 に答える 2

4

あなたの主な問題は、レクサーをパーサーに含めようとしていることです。あなたが (少なくとも通常は) やりたいことは、 を使用して 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();
}

それ以外に、あなたの文法には、あなたが本当に意図したものとはかなり違うと確信している小さな詳細が 1 つまたは 2 つあります。例えば:

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

おそらく、「while」に一致した場合、「printf」ではなく「while」を出力したいでしょう。

|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」を出力したいと思います。

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

もちろん、アクションを別の行に配置するなど (特にアクションが長い場合)、これを変更することはできますが、一般的な考え方は変わりません。あるルールがどこで終了し、別のルールが開始するかを示すのに、コメントは必要ありません。書式を設定すると、それが明確になります。

編集: もう 1 つの点について言及するのを忘れていました: ボトムアップ パーサー (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");}
    ;
于 2010-04-20T15:51:29.310 に答える
0

これが例です。JMP命令はラベルL1に送られます。

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

ありがとう。

于 2010-04-26T10:43:40.710 に答える