Синтаксическая ошибка при тестировании пустого файла - LEX / YACC - PullRequest
0 голосов
/ 21 октября 2018

Итак, в основном, я получаю синтаксическую ошибку всякий раз, когда тестирую пустой файл или файл, содержащий только комментарий.Ошибка выглядит следующим образом: enter image description here

test01 - это просто пустой файл .c

Вот мой файл Lex:

%{
/*constants are defined outside of the l file in y.tab.h
*constants are defined from 257
*/

#include "y.tab.h"
int input_line_no = 1;
char the_tokens[1000];
char full_line[1000];
int lex_state = 0;

%}

whitespace         [ \t]
number             [0-9]
letter             [A-Za-z]
alfanum            [A-Za-z0-9_]
intcon             {number}+
id                 {letter}{alfanum}*
anything           .

%option noyywrap
 /*
 *Start conditions are specified to identify comments, 
 *literal strings, and literal chars. 
 */

%Start comment_in comment_out string_in char_in

%%

/*tokenization of special strings*/
"extern"        {return EXTERN;}
"if"            {return IF;}
"else"          {return ELSE;}
"void"          {return VOID;}
"char"          {return CHAR;}
"int"           {return INT;}



 /*line number is recorded*/
[\n]                        input_line_no++;

 /*identify comment*/
<INITIAL>"/""*"      {
                lex_state=1;
                                BEGIN(comment_in);
                 }
<comment_in>"*"      BEGIN(comment_out);
<comment_in>[^*]     ;
<comment_out>"*"     ;
<comment_out>"/"     {
            lex_state = 0;
                    BEGIN(INITIAL);
                 }
<comment_out>[^*/]   BEGIN(comment_in);

/*start tokenization of strings*/
<INITIAL>\"             {
            lex_state = 2;
                            BEGIN(string_in);

                    }
<string_in>[^"]     {
            return STRINGCON;
        }
<string_in>\"       {
            lex_state = 0;
            BEGIN(INITIAL);
        }
 /*tokenization of characters*/
<INITIAL>\' {
        lex_state = 3;
        BEGIN(char_in);
    }
<char_in>[^']
     {
         return CHARCON;
     }
<char_in>\' {
        lex_state = 0;
        BEGIN(INITIAL);
    }

{whitespace}    ;

 /*tokenization of numbers*/
{intcon}         {return(INTCON);}
{id}        {return ID;}

/*tokenization of operations*/
"=="        {return EQUALS;}
"!="        {return NOTEQU;}
">="        {return GREEQU;}
"<="        {return LESEQU;}
">"     {return GREATE;}
"<"     {return LESSTH;}

"&&"        {return ANDCOM;}
"||"        {return ORCOMP;}
"!"             {return ABANG;}

";"     {return SEMIC;}
","     {return COMMA;}
"("     {return LPAR;}
")"     {return RPAR;}      
"["     {return LBRAC;}
"]"     {return RBRAC;}
"{"     {return LCURL;}
"}"     {return RCURL;}

"+"     {return ADD;}
"-"     {return SUB;}
"*"     {return MUL;}
"/"     {return DIV;}
"="     {return EQUAL;}

 /*For strings that can not be identified by any patterns specified previously
 *lex returns the value of the character
 */

  {anything}     {return(OTHER);}

%%

Вот мой файл Yacc:

    %{

#include <stdio.h>
#define YDEBUG
#ifndef YDEBUG

#define Y_DEBUG_PRINT(x)

#else

#define Y_DEBUG_PRINT(x) printf("Yout %s \n ",x)

#endif
int yydebug = 1; 

extern char the_token[]; 
 /* This is how I read tokens from lex... :) */
extern int input_line_no; 
 /* This is the current line number */
extern char *full_line; 
 /* This is the full line */
extern int lex_state;


%}

%token STRINGCON CHARCON INTCON EQUALS NOTEQU GREEQU LESEQU GREATE LESSTH
%token ANDCOM ORCOMP SEMIC COMMA LPAR RPAR LBRAC RBRAC LCURL RCURL ABANG
%token EQUAL ADD SUB MUL DIV ID EXTERN FOR WHILE RETURN IF ELSE 
%token VOID CHAR INT OTHER

%left ORCOMP
%left ANDCOM
%left EQUALS NOTEQU
%left LESSTH GREATE LESEQU GREEQU
%left ADD SUB
%left MUL DIV
%right UMINUS
%right ABANG

%start Assign
%%

prog: dcl SEMIC prog2 {Y_DEBUG_PRINT("prog-dcl-SEMIC-prog2");}
| Function prog2 {Y_DEBUG_PRINT("prog-Function-prog2");}

prog2: {Y_DEBUG_PRINT("prog2-EMPTY");}
| dcl SEMIC prog2 {Y_DEBUG_PRINT("prog2-dcl-SEMIC-prog2");}
| Function  prog2 {Y_DEBUG_PRINT("prog2-Function-prog2");}

dcl: VAR_list {Y_DEBUG_PRINT("dcl-VAR_list");}
| ID LPAR Param_types RPAR dcl2 {Y_DEBUG_PRINT("dcl-ID-LPAR-Param_types-RPAR-dcl2");}
| EXTERN ID LPAR Param_types RPAR dcl2 {Y_DEBUG_PRINT("dcl-EXTERN-ID-LPAR-Param_types-RPAR-dcl2");}
| EXTERN Type ID LPAR Param_types RPAR dcl2 {Y_DEBUG_PRINT("dcl-EXTERN-Type-ID-LPAR-Param_types-RPAR-dcl2");}
| EXTERN VOID ID LPAR Param_types RPAR dcl2 {Y_DEBUG_PRINT("dcl-EXTERN-VOID-ID-LPAR-Param_types-RPAR-dcl2");}
| Type ID LPAR Param_types RPAR dcl2 {Y_DEBUG_PRINT("dcl-Type-ID-LPAR-Param_types-RPAR-dcl2");}
| VOID ID LPAR Param_types RPAR dcl2 {Y_DEBUG_PRINT("dcl-VOID-ID-LPAR-Param_types-RPAR-dcl2");}

dcl2: {Y_DEBUG_PRINT("dcl2-EMPTY");}
| COMMA ID LPAR Param_types RPAR dcl2 {Y_DEBUG_PRINT("dcl2-COMMA-ID-LPAR-Param_types-RPAR-dcl2");}

Function: Functionhead LCURL Functionbody RCURL {Y_DEBUG_PRINT("Function-Functionhead-LCURL-Functionbody-RCURL");}
| VOID Functionhead LCURL Functionbody RCURL {Y_DEBUG_PRINT("Function-VOID-Functionhead-LCURL-Functionbody-RCURL");}
| Type Functionhead LCURL Functionbody RCURL {Y_DEBUG_PRINT("Function-Type-Functionhead-LCURL-Functionbody-RCURL");}

Functionhead: ID LPAR Param_types RPAR {Y_DEBUG_PRINT("Functionhead-ID-LPAR-Param_types-RPAR");}

Functionbody: VAR_list STMT_list {Y_DEBUG_PRINT("Functionbody-Varlist-Stmtlist");}

Param_types: VOID {Y_DEBUG_PRINT("Param_types-VOID");}
|Param_types1 {Y_DEBUG_PRINT("Param_types-Param_types1");}

Param_types1: Param_type1 {Y_DEBUG_PRINT("Param_types1-Param_type1");}
| Param_types1 COMMA Param_type1 {Y_DEBUG_PRINT("Param_types1-Param_types1-COMMA-Param_type1");}

Param_type1: Type ID Param_type11 {Y_DEBUG_PRINT("PARAM_type1-Type-ID-Param_type11");}

Param_type11: {Y_DEBUG_PRINT("Param_type11-EMPTY");}
| LBRAC RBRAC {Y_DEBUG_PRINT("Param_type11-LBRAC-RBRAC");}

VAR_list: Type VAR_list2 {Y_DEBUG_PRINT("VAR_list-Type-VAR_list2");}

VAR_list2: var_decl {Y_DEBUG_PRINT("VAR_list2-var_decl");}
| var_decl COMMA VAR_list2 {Y_DEBUG_PRINT("VAR_list2-var_decl-COMMA-VAR_list2");}

var_decl: ID {Y_DEBUG_PRINT("var_decl-ID");}
| ID LBRAC INTCON RBRAC {Y_DEBUG_PRINT("var-decl-ID-LBRAC-INTCON-RBRAC");}

Type: CHAR {Y_DEBUG_PRINT("Type-CHAR");}
|INT {Y_DEBUG_PRINT("Type-INT");}

STMT_list: STMT2 {Y_DEBUG_PRINT("STMT-list-STMT2");}

STMT2: STMT {Y_DEBUG_PRINT("STMT2-STMT");}
| STMT STMT2 {Y_DEBUG_PRINT("STMT2-STMT-STMT2");}

STMT : IF LPAR Expr RPAR STMT {Y_DEBUG_PRINT("IF-LPARN-Expr-RPARN-STMT");}
| IF LPAR Expr RPAR STMT ELSE STMT{Y_DEBUG_PRINT("IF-LPARN-Expr-RPARN-STMT-ELSE-STMT");}
 /*if cats) ERROR*/
| IF Expr RPAR STMT ELSE STMT {warn("STMT-IF: missing LPAR");}
 /*if (cats ERROR*/
| IF LPAR Expr STMT ELSE STMT {warn("STMT-IF: missing RPAR");}
 /*two elses ERROR*/
| IF LPAR Expr STMT ELSE ELSE STMT {warn(":too many elses");}
| WHILE LPAR Expr RPAR STMT{Y_DEBUG_PRINT("STMT-WHILE-LPAR-Expr-RPAR-STMT");}
 /*for(c=0;c<1;c++)*/
| FOR LPAR Assign SEMIC Expr SEMIC Assign RPAR STMT {Y_DEBUG_PRINT("STMT-FOR-LPAR-Assign-SEMIC-Expr-SEMIC-Assign-RPAR-STMT");}
 /*for(;c<1;c++)*/
| FOR LPAR SEMIC Expr SEMIC Assign RPAR STMT {Y_DEBUG_PRINT("STMT-FOR-LPAR-SEMIC-Expr-SEMIC-Assign-RPAR-STMT");}
 /*for(;;c++)*/
| FOR LPAR SEMIC SEMIC Assign RPAR STMT {Y_DEBUG_PRINT("STMT-FOR-LPAR-SEMIC-SEMIC-Assign-RPAR-STMT");}
 /*for(;;)*/
| FOR LPAR SEMIC SEMIC RPAR STMT {Y_DEBUG_PRINT("STMT-FOR-LPAR-SEMIC-SEMIC-RPAR-STMT");}
 /*for(c=0;;)*/
| FOR LPAR Assign SEMIC SEMIC RPAR STMT {Y_DEBUG_PRINT("STMT-FOR-LPAR-Assign-SEMIC-SEMIC-RPAR-STMT");}
 /*for(c=0;c<1;)*/
| FOR LPAR Assign SEMIC Expr SEMIC RPAR STMT {Y_DEBUG_PRINT("STMT-FOR-LPAR-Assign-SEMIC-Expr-Semic-RPAR-STMT");}
 /*for(c=0;;c++)*/
| FOR LPAR Assign SEMIC SEMIC Assign RPAR STMT {Y_DEBUG_PRINT("STMT-FOR-LPAR-Assign-SEMIC-SEMIC-ASSIGN-RPAR-STMT");}
 /*for(;c<1;)*/
| FOR LPAR SEMIC Expr SEMIC RPAR STMT {Y_DEBUG_PRINT("STMT-FOR-LPAR-SEMIC-Expr-SEMIC-RPAR-STMT");}
 /*for() ERROR*/
| FOR LPAR RPAR STMT {warn("STMT-FOR: empty statement");}
 /*for{;;;) ERROR*/
| FOR LPAR SEMIC SEMIC SEMIC RPAR {warn("STMT-FOR: too many semicolons");}
 /*for;;) ERROR*/
| FOR SEMIC SEMIC RPAR STMT {warn("STMT-FOR: missing LPAR");}
 /*for(;; ERROR*/   
| FOR LPAR SEMIC SEMIC STMT {warn("STMT-FOR: missing RPAR");}
| RETURN Expr SEMIC {Y_DEBUG_PRINT("STMT-RETURN-Expr-SEMIC");}
| RETURN SEMIC {Y_DEBUG_PRINT("STMT-RETURN-SEMIC");}
 /*return ERROR*/
| RETURN {warn("STMT-Return:missing semicolon");}
| Assign SEMIC {Y_DEBUG_PRINT("STMT-Assign-SEMIC");}
/*function call*/
| ID LPAR RPAR SEMIC {Y_DEBUG_PRINT("STMT-ID-LPAR-RPAR-SEMIC");}
| ID LPAR Expr Expr2 RPAR SEMIC {Y_DEBUG_PRINT("STMT-ID-LPAR-Expr-Expr2-RPAR-SEMIC");}
 /*No semic ERROR*/
| ID LPAR Expr Expr2 RPAR {warn(":missing semicolon");}  
| LCURL STMT2 RCURL {Y_DEBUG_PRINT("STMT-LCURL-STMT-RCURL");}
| LCURL RCURL {Y_DEBUG_PRINT("STMT-LCURL-RCURL");}
| SEMIC {Y_DEBUG_PRINT("STMT-SEMIC");}

Assign : ID Assign1 EQUAL Expr {Y_DEBUG_PRINT("Assign-1-ID-Assign1-EQUAL-Expr");}
 /*Error no semi*/
| Assign {warn( "Assign: missing semicolon on line");}

Assign1 : {Y_DEBUG_PRINT("Assign1-1-Empty"); }
| LBRAC Expr RBRAC {Y_DEBUG_PRINT("Assign1-2-LBRAC-Expr-RBRAC"); }
| LBRAC Expr error { warn("Assign1: missing RBRAC"); }
| error Expr RBRAC { warn("Assign1: missing LBRAC"); }
| LBRAC error RBRAC { warn("Assign1: Invalid array index"); }

Expr : SUB Expr %prec UMINUS {Y_DEBUG_PRINT("Expr-1-UMINUS Expr"); }
| ABANG Expr {Y_DEBUG_PRINT("Expr-2-ANABG Expr"); }
| Expr Binop Expr {Y_DEBUG_PRINT("Expr-3-Expr-Binop-Expr"); }
| Expr Relop Expr {Y_DEBUG_PRINT("Expr-4-Expr-Binop-Expr"); }
| Expr Logop Expr {Y_DEBUG_PRINT("Expr-5-Expr-Logop-Expr"); }
| ID {Y_DEBUG_PRINT("Expr-6-ID"); }
| ID LPAR RPAR {Y_DEBUG_PRINT("Expr-ID-LPAR-RPAR");} 
| ID LPAR Expr Expr2 RPAR {Y_DEBUG_PRINT("Expr-ID-LPAR-Expr-Expr2-RPAR");}
| ID LBRAC Expr RBRAC {Y_DEBUG_PRINT("Expr-ID-LBRAC-Expr-RBRAC");}
| LPAR Expr RPAR {Y_DEBUG_PRINT("Expr-7-LPARN-Expr-RPARN");} 
| INTCON { Y_DEBUG_PRINT("Expr-8-INTCON"); }
| CHARCON { Y_DEBUG_PRINT("Expr-9-CHARCON"); }
| STRINGCON { Y_DEBUG_PRINT("Expr-10-STRINGCON"); }
| Array {Y_DEBUG_PRINT("Expr-11-Array"); }
| error {warn("Expr: invalid expression "); }

/*top is for no expression 2*/
Expr2: {Y_DEBUG_PRINT("Expr2-Empty");}
| COMMA Expr {Y_DEBUG_PRINT("Expr2-COMMA-Expr");}
 /*recursively looks for another expression in function call (exp1,exp2,exp3,...*/
| COMMA Expr Expr2 {Y_DEBUG_PRINT("Expr2-COMMA-Expr-Expr2");}


Array : 
ID LBRAC Expr RBRAC {Y_DEBUG_PRINT("Array-1-ID-LBRAC-Expr-RBRAC"); }
| ID error RBRAC {warn( "Array: invalid array expression"); }

Binop : ADD {Y_DEBUG_PRINT("Binop-1-ADD"); }
| SUB {Y_DEBUG_PRINT("Binop-2-SUB"); }
| MUL {Y_DEBUG_PRINT("Binop-3-MUL"); }
| DIV {Y_DEBUG_PRINT("Binop-4-DIV"); }

Logop : ANDCOM {Y_DEBUG_PRINT("Logop-1-ANDCOM"); }
| ORCOMP {Y_DEBUG_PRINT("Logop-2-ORCOMP"); }

Relop : EQUALS { Y_DEBUG_PRINT("Relop-1-EQUALS"); }

| NOTEQU { Y_DEBUG_PRINT("Relop-2-NOTEQU"); }

| LESEQU { Y_DEBUG_PRINT("Relop-3-LESEQU"); }

| GREEQU { Y_DEBUG_PRINT("Relop-4-GREEQU"); }

| GREATE { Y_DEBUG_PRINT("Relop-5-GREATE"); }

| LESSTH { Y_DEBUG_PRINT("Relop-6-LESSTH"); }


%%

main()
{
int result = yyparse();
if (lex_state==1) {
yyerror("End of file within a comment");
}
if (lex_state==2) {
yyerror("End of file within a string");
}
return result;
} 
int yywrap(){
return 1;
}
yyerror(const char *s)
{
fprintf(stderr, "%s on line %d\n",s,input_line_no);
} 
warn(char *s)
{
fprintf(stderr, "%s\n", s);
}

По сути, это должен быть лексический анализатор и парсерная часть компилятора.Я пытаюсь разобрать код из-за правил C- грамматики.Я попытался добавить правило конца файла в Lexer, но оно просто выдало ту же ошибку, что и раньше, поэтому я не думаю, что это проблема.

Есть ли способ узнать, прошел ли Lexerправильные токены парсеру?

Кроме того, мне сказали проверить файл y.output, чтобы увидеть, как исправить ошибки сдвига / уменьшения для моего синтаксического анализатора, но я посмотрел на файл и не знаю, как сказатьгде ошибки.

Я знаю, что, вероятно, есть много проблем с моим кодом Yacc, но в настоящее время я просто пытаюсь исправить эту единственную ошибку, чтобы я мог работать с другими.Спасибо за любую помощь, спасибо.

1 Ответ

0 голосов
/ 22 октября 2018

Проблема в том, что ваша грамматика не соответствует пустому вводу, поэтому, если вы дадите ей какой-либо пустой ввод, он помечает ее как ошибку synatx.Ваша грамматика особенно запутана, поскольку она даже не принимает ни одного объявления или функции, она требует не менее 2.

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

prog: /* empty */
    | prog decl SEMIC
    | prog Function
    ;
...