2017-11-15 32 views
0

내 파서에서 읽을 수 있습니다 파일이 있습니다 오류가 PRINT 토큰 주위에 발생하는구문 들소 오류 토큰 읽기

BEGINING. 

XXX XY-1. 

XXXX Y. 

XXXX Z. 

BODY. 

PRINT "Please enter a number?". 

END. 

있는 test.txt를. 어휘 분석기에서 문자열 "Please enter a number?"이 제대로 처리되고 있습니다. 콘솔에 출력했기 때문에 이것을 알고 있습니다. PRINT keywor는 어휘 분석기에서 반환 될 때

lexer.I 파서 이제

%{ 
#include <stdio.h> 

#include "parser.tab.h" 
#define YYSTYPE char * 
%} 

%option noyywrap 
%option caseless 

%% 

(?i:BEGINING) return TERM_BEGINING; 
(?i:BODY) return TERM_BODY; 
(?i:END) return TERM_END; 
(?i:MOVE) return TERM_MOVE; 
(?i:TO) return TERM_TO; 
(?i:ADD) return TERM_ADD; 
(?i:INPUT) return TERM_INPUT; 
(?i:PRINT) return TERM_PRINT; 


[\t| ]+ // ignore whitespaces 

\n // Ignore new line 

[X]+ yylval.integer = yyleng; return TERM_SIZE; 

[\"][^"]*[\"] yylval.string = strdup(yytext); printf("%s\n", yytext); return TERM_STR; 

";" return TERM_SEPARATOR; 

"." return TERM_FULLSTOP; 

[0-9]+ yylval.integer = atoi(yytext); return TERM_INT; 

[\_\-0-9][a-zA-Z][a-zA-Z0-9\-\_]* yylval.string = strdup(yytext); return TERM_INVALID_VARIABLE_NAME; 

[A-Z][A-Z0-9\-]* yylval.string = strdup(yytext); return TERM_VARIABLE_NAME; 

. return TERM_INVALID_TOKEN; 

%% 

//int main(int argc, char** argv) { 
// if (argc != 2) { 
//  yyin = stdin; 
//  yylex(); 
// } else { 
//  FILE* aFile = fopen(argv[1], "r"); 
//  if (!aFile) { 
//   printf("Cannot open file!\n"); 
//   return -1; 
//  } else { 
//   yyin = aFile; 
//   yylex(); 
//   fclose(yyin); 
//  } 
// } 
//} 

는 디버깅 목적으로, 나는 단어 PRINT

parser.y

를 인쇄하기로 결정했습니다
%{ 
//yylval - externalise variable in which yylex should place semantic value associated with a token 
//yyparse - parser function produced by bison, call this to start parsing 

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <math.h> 
#include <unistd.h> 

extern FILE* yyin; 
typedef int bool; 

#define true 1 
#define false 0 

//Cause an immediate syntax error 
int yyerror(char *s) { 
    fprintf(stderr, "%s\n", s); 
    exit(0); 
} 

//Declare yylex, user supplied lexical analyzer function to get the next token 
int yylex(void); 

//yywrap text wrap 
//When scanner recieves EOF it checks yywrap() 
int yywrap(void) { 
    return 1; 
} 

// Structure of variable 
struct variable { 
    char* varName; 
    int varSize; 
    int varValue; 
}; 

typedef struct { 
    struct variable* array; 
    size_t used; 
    size_t size; 
} Array; 

// Method declarations 
void writeToWarning(char *aWarning); 
void writeError(char *anError); 
void writeToLog(char *alog); 
bool checkIfDeclared(char* varName); 

void initialiseArray(Array *a, size_t initialSize); 
void insertArray(Array *a, struct variable *aVar); 
void freeArray(Array *a); 

void createVar(int size, char* varName); 
void inputValues(char* varName); 


%} 

//each token is a terminal 
%token TERM_BEGINING TERM_BODY TERM_END TERM_MOVE 
     TERM_TO TERM_ADD TERM_INPUT TERM_PRINT 
     TERM_SIZE TERM_STR TERM_SEPARATOR TERM_FULLSTOP 
     TERM_INT TERM_INVALID_VARIABLE_NAME TERM_VARIABLE_NAME TERM_INVALID_TOKEN 

//Everything that something can be 
//yyvval array from lexer.l 
%union { 
    int integer; 
    char* string; 
} 

//Define anything that the lexer can return as a string or integer 
%type<integer> TERM_INT 
%type<integer> TERM_SIZE 
%type<string> TERM_STR 
%type<string> TERM_SEPARATOR 
%type<string> TERM_FULLSTOP 
%type<string> TERM_VARIABLE_NAME 
%type<string> TERM_INVALID_VARIABLE_NAME 

%% 

// Create grammer 

program: 
    /* empty */ | 
    begin middle_declarations body grammar_s end { 
     printf("Parsing complete\n"); 
     exit(0); 
    }; 

begin: 
    TERM_BEGINING TERM_FULLSTOP; 

body: 
    TERM_BODY TERM_FULLSTOP; 

end: 
    TERM_END TERM_FULLSTOP; 

middle_declarations: 
    /* empty */ | 
    //Left recursive to allow for many declearations 
    middle_declarations declaration TERM_FULLSTOP; 

declaration: 
    TERM_SIZE TERM_VARIABLE_NAME { 
     createVar($1, $2); 
    }; 

grammar_s: 
    /* empty */ | 
    grammar_s grammar TERM_FULLSTOP; 

grammar: 
    add | move | print | input; 

add: 
    TERM_ADD TERM_VARIABLE_NAME TERM_TO TERM_VARIABLE_NAME { 
     //addVarToVar($2, $4); 
    } 

    TERM_ADD TERM_INT TERM_TO TERM_VARIABLE_NAME { 
     //addNumToVar($2, $4); 
    } 

    ; 

move: 
    TERM_MOVE TERM_VARIABLE_NAME TERM_TO TERM_VARIABLE_NAME { 
     //moveVarToVar($2, $4); 
    } 

    TERM_MOVE TERM_INT TERM_TO TERM_VARIABLE_NAME { 
     //moveNumToVar($2, $4); 
    } 

    ; 

print: 
    TERM_PRINT rest_of_print { 
     printf("PRINT\n"); 
    }; 

rest_of_print: 
    /* empty */ | 
    rest_of_print other_print; 

other_print: 
    TERM_VARIABLE_NAME { 
     //printVarName($1); 
    } 

    TERM_INVALID_VARIABLE_NAME { 
     //printInvalidVarName($1); 
    } 

    TERM_SEPARATOR { 
     printf("%s", $1); 
    } 

    TERM_STR { 
     printf("STRING%s%s", $1, "\n"); 
    } 

    ; 

input: 
    // Fullstop declares grammar 
    TERM_INPUT other_input; 

other_input: 

    /* empty */ | 
    // Input var1 
    TERM_VARIABLE_NAME { 
     inputValues($1); 
    } 

    // Can be input var1 
    TERM_VARIABLE_NAME TERM_SEPARATOR { 
     //inputValues($2); 
    } 

    ; 

%% 

Array a; 

void initialiseArray(Array *a, size_t initialSize) { 
    a->array = (struct variable*) malloc(initialSize * sizeof(struct variable)); 
    a->used = 0; 
    a->size = initialSize; 
} 

void insertArray(Array *a, struct variable *aVar) { 
    if (a->used == a->size) { 
     a->size *= 6; 
     a->array = (struct variable*) realloc(a->array, a->size * sizeof(struct variable)); 
    } 
    a->array[a->used++] = *aVar; 
} 

void freeArray(Array *a) { 
    free(a->array); 
    a->array = NULL; 
    a->used = a->size = 0; 
} 

void createVar(int size, char* varName) { 

    printf("SIZE: %d\n", size); 
    printf("NAME: %s\n", varName); 

    bool alreadyDeclared; 
    alreadyDeclared = checkIfDeclared(varName); 
    if (!alreadyDeclared) { 
     struct variable aVar; 
     aVar.varName = varName; 
     aVar.varSize = size; 
     aVar.varValue = 0; 

     insertArray(&a, &aVar); 

     writeToLog("Created variable succesfully\n"); 
    } else { 
     writeToWarning("Variable has already been declared\n"); 
    } 
} 

bool checkIfDeclared(char* varName) { 
    for (int i = 0; i < a.used; i++) { 
     if (strcmp(a.array[i].varName, varName) == 0) { 
      return 1; 
     } 
    } 
    return 0; 
} 

void inputValues(char* varName) { 
    printf("VAR_NAME: %s\n", varName); 
} 

int main(int argc, char* argv[]) { 

    if (argc != 2) { 
     yyin = stdin; 
     yylex(); 
    } else { 
     FILE* aFile = fopen(argv[1], "r"); 
     if (!aFile) { 
      printf("Cannot open file!\n"); 
      return -1; 
     } else { 
      int i; 
      initialiseArray(&a, 5); 

      yyin = aFile; 
      yyparse(); 
     } 
    } 

    fclose(yyin); 
    freeArray(&a); 



// for (int i = 0; i < 10; i++) { 
    // struct variable aVar; 
    // aVar.varName = "TEST_VAR"; 
    // aVar.varSize = 0; 
    // aVar.varValue = 0; 

    // insertArray(&a, &aVar); 
    //} 

    //for (int j = 0; j < a.used; j++) { 
    // printf("Name: %s\n", a.array[j].varName); 
    //} 
    //printf("Name: %s\n", a.array[9].varName); 
    //printf("Used: %zu\n", a.used); 

    //yyparse(); 

    //if (argc > 0) { 
    // freeArray(&a); 
    // fclose(yyin); 
    //} 
    return 0; 
} 

void writeToWarning(char *aWarning){ 
    printf("Warning : %s%s", aWarning,"\n"); 
} 

void writeError(char *anError){ 
    printf("Error : %s%s", anError,"\n"); 
} 

void writeToLog(char *alog){ 
    printf("Success : %s%s", alog,"\n"); 
} 

이것은 내가 컴파일하는 방법이다

이 0 내가

./parser test.txt 

실행 그런 다음이 내가 작업을 (문법을 변경하지 않는) 당신의 other_print 규칙이 밖으로 떠나

SIZE: 3 // this is output from the createVar function 
NAME: XY-1 
Success : Created variable succesfully 

SIZE: 4 
NAME: Y 
Success : Created variable succesfully 

SIZE: 4 
NAME: Z 
Success : Created variable succesfully 

"Please enter a number?" // This is output for debugging from the lexer 
PRINT // This is output for debugging from the parser, 
syntax error 
+2

'other_input'과'other_print' 프로덕션에서'|'s가 누락 된 것 같아요. – rici

+0

@rici 감사합니다. 실종되었습니다. | other_print에있는 작품 중 하나 사이 – cod3min3

+1

그런데 캐릭터 클래스에있는'\ '기호 중 어느 것도 필요하지 않으며'[\ t | ]'''는 공백 문자가 아니기 때문에' – rici

답변

2

를 얻을 수 출력 방법입니다 :

other_print: 
    TERM_VARIABLE_NAME TERM_INVALID_VARIABLE_NAME TERM_SEPARATOR TERM_STR 

홀수 번째 터미널이 입력 파일에 존재하지 않으므로 productio n이 일치하지 않아 구문 오류보고가 표시됩니다.

실제로 구문을 원했을 가능성은 희박합니다. 제 추측으로는 네 개의 터미널이 연결이 아닌 대안이되도록 의도 한 것입니다. 그렇다면 | 초로 구분해야합니다.

other_input도 비슷한 문제가 있습니다.