2017-08-15 6 views
0

コンパイラを作成する基本的な概念を理解しようとしています。私は非常に基本的なCコンパイラを作成しようとしましたが、いくつかの問題が発生しました。変数yylinenoで構文エラーが発生した箇所を印刷しようとすると、行番号の一部が間違っています。なぜ誰が知っていますか?私はインターネットを検索しましたが、私は明確な答えを見つけることができません、ありがとう。yylinenoがエラー報告のために予期しない結果を出す

comp.lファイル:

%{ 
#include <stdio.h>  
#include <stdlib.h> 
#include <string.h> 


extern int yylineno; 
extern FILE* yyin; 
//extern char* yytext; 
void yyerror(char *s); 


%} 


%union {char* var;} 

%token INT FLOAT CHAR DOUBLE VOID 
%token FOR WHILE 
%token IF ELSE PRINTF 
%token STRUCT 
%token NUM 
%token INCLUDE 
%token DOT 
%token <var> ID 
%right '=' 
%left AND OR 
%left '<' '>' LE GE EQ NE LT GT 
%error-verbose 

%% 

start: Function 
    | Declaration 
    ; 

/* Declaration block */ 
Declaration: Type Assignment ';' 
    | Assignment ';'  
    | FunctionCall ';' 
    | ArrayUsage ';'  
    | Type ArrayUsage ';' 
    | StructStmt ';'  
    | Arg ';' 
    | error {yyerrok;} 
    ; 

/* Assignment block */ 
Assignment: ID '=' Assignment 
    | ID '=' FunctionCall 
    | ID '=' ArrayUsage  
    | ArrayUsage '=' Assignment 
    | ID ',' Assignment 
    | NUM ',' Assignment 
    | ID '+' Assignment  
    | ID '-' Assignment  
    | ID '*' Assignment  
    | ID '/' Assignment  
    | NUM '+' Assignment 
    | NUM '-' Assignment 
    | NUM '*' Assignment 
    | NUM '/' Assignment 
    | '\'' Assignment '\'' 
    | '(' Assignment ')' 
    | '-' '(' Assignment ')' 
    | '-' NUM 
    | '-' ID 
    | NUM 
    | ID 
    ; 

/* Function Call Block */ 
FunctionCall : ID'('')' 
    | ID'('Assignment')' 
    ; 

/* Array Usage */ 
ArrayUsage : ID'['Assignment']' 
    | ID'['error ']' {yyerrok;} 
    ; 

/* Function block */ 
Function: Type ID '(' ArgListOpt ')' CompoundStmt 

ArgListOpt: ArgList 
    | 
    ; 

ArgList: ArgList ',' Arg 
    | Arg 
    ; 

Arg: Type ID 
    ; 

CompoundStmt: CompoundStmt '{' StmtList '}' 
    | '{' StmtList '}' 
    | '{' StmtList {yyerror("Missing '}'"); YYERROR;} 
    | StmtList '}' {yyerror("Missing '{'"); YYERROR;} 
    ; 

StmtList: StmtList Stmt 
    | 
    ; 

Stmt: WhileStmt 
    | Declaration 
    | ForStmt 
    | IfStmt 
    | PrintFunc 
    | ';' 
    ; 

/* Type Identifier block */ 
Type: INT 
    | FLOAT 
    | CHAR 
    | DOUBLE 
    | VOID 
    ; 

/* Loop Blocks */ 
WhileStmt: WHILE '(' Expr ')' Stmt 
    | WHILE '(' Expr ')' CompoundStmt 
    ; 

/* For Block */ 
ForStmt: FOR '(' Expr ';' Expr ';' Expr ')' Stmt 
     | FOR '(' Expr ';' Expr ';' Expr ')' CompoundStmt 
     | FOR '(' Expr ')' Stmt 
     | FOR '(' Expr ')' CompoundStmt 
    ; 

/* IfStmt Block */ 
IfStmt : IF '(' Expr ')' Stmt 
    ; 

/* Struct Statement */ 
StructStmt : STRUCT ID '{' Type Assignment '}' 
    ; 

/* Print Function */ 
PrintFunc : PRINTF '(' Expr ')' ';' 
    ; 

/*Expression Block*/ 
Expr: 
    | Expr LE Expr 
    | Expr GE Expr 
    | Expr NE Expr 
    | Expr EQ Expr 
    | Expr GT Expr 
    | Expr LT Expr 
    | Assignment 
    | ArrayUsage 
    ; 

%% 

int count = 0; 







int main() { 

    int i; 

    for(i=0; i<100; i++) { 

     variables[i] = " "; 

    } 

    yyin = stdin; 

    do { 

     yyparse(); 

    } while(!feof(yyin)); 

    return 0; 
} 





void yyerror(char* s) { 




    printf("Error : %s at line %d \n", s, yylineno); 

} 

comp.yファイル:たとえば

alpha [a-zA-Z] 
digit [0-9] 

%{ 
#include "y.tab.h" 
#include <stdio.h> 

int line_n = 1; 

%} 

%option nodefault yylineno 



%% 


[\t\n]+      {;} 
"int"      {return INT;} 
"float"      {return FLOAT;} 
"char"      { return CHAR;} 
"void"      {return VOID;} 
"double"      {return DOUBLE;} 
"for"      {return FOR;} 
"while"      {return WHILE;} 
"if"       {return IF;} 
"else"      {return ELSE;} 
"printf"      {return PRINTF;} 
"struct"      {return STRUCT;} 
^"#include ".+    {;} 
{digit}+      {return NUM;} 
{alpha}({alpha}|{digit})* {yylval.var = strdup(yytext);return ID;} 
"<="       {return LE;} 
">="       {return GE;} 
"=="       {return EQ;} 
"!="       {return NE;} 
">"       {return GT;} 
"<"       {return LT;} 
"."       {return DOT;} 
\/\/.*      {;} 
\/\*(.*\n)*.*\*\/   {;} 
[ \t\r\n]+     {;} 
.       {return *yytext;} 


%% 



int yywrap (void) {return 1;} 

、私は次のコードをチェックしてみてください:私を得る

1.int main(){ 
2. int a 
3. 
4. 
5. 
6. int o 
7.} 

エラー:構文エラー、予期しないINT、 ';'行6で

エラー:予期しない '}'、予期している ';' 7行目

答えて

1

Cコードの例では、エラーの行番号は正しいです。 2行目のint aの後ろにある;が、その行にあり、例えば、4,5行目、またはという行でさえされていない必要はありません。

int o

線6にも有する}はどちら;を逃すものの7

その定義と同じ行にあることが要求されるラインに満たされた場合にのみ明らかにされる;、第1の欠落行番号かもしれないかもしれないが出現しました。代わりに最後の行番号でなければならないと報告されています。

MSVCプログラムに貼り付けた例では、エラーの行番号と同じパターンが報告されます。

+0

gccやclangコンパイラのようなエラー行番号を表示するには、より良い方法がありますか? –

+0

@ omn_1私はそれらを使用しません。コンパイラの報告書が何を期待するのかという疑問を投稿してください。 –

+1

@ omn_1:gccは手書きのレクサーを使用していますが、これはlexよりも簡単ですが、テクニックは簡単です。各レクメムにソース行(および/または追加の再配置情報)を付けます。次に、エラーが発生した場合、エラー回復中に、保存された情報を使用して、「現在の行」よりも面白い行を印刷します。 – torek

関連する問題