2017-01-02 6 views
-1

単純な書式言語のコンパイラを作成しようとしていますが、 Bisonが認識したときの出力ファイルへのメッセージFlex/Bison(Lex/Yacc)で2行の順序を変更した場合、出力ファイルへの出力が機能しない

beginDocument docProperties endDocument 

まず、機能が期待どおりに機能する.yファイルを表示します。しかし、私はコードの2行だけの順序を変更し、出力ファイルへの印刷はもはや機能しません!

これは正常に動作します.Yファイルです:入力ファイルとしてこれにより

%{ 
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <string.h> 
    #include "y.tab.h" 
    void yyerror(const char *); 
    int yylex(void); 

    /* "Connect" with the output file */ 
    extern FILE *yyout; 
    extern int yylineno; 

    /* Integers related to user-defined document properties */ 
    int tabSize, linesPerPage, charsPerLine, linesPrinted, pageNumber = 1; 

    char* title; /* char* title, author, date; is wrong. In C that would have been char *title, *author, *date because typically in C it's int *p while in C++ it's int* p */ 
    char* author; 
    char* date; 

    /* An array with counters of how many times each of the 5 document properties appears in the input file. The order of the properties is defined in the enum below */ 
    int docPropertyCounters[5]; 

    /* An enumerated list with the 5 document properties */ 
    typedef enum {PAGE_SETUP, TAB_SIZE, DOC_TITLE, DOC_AUTHOR, DOC_DATE} document_property; 

    /* Takes a document_property enum (basically an integer) and returns the corresponding document property as a string. The order is based on the enum. */ 
    static inline char *stringFromDocPropertyEnum(const document_property indexOfProperty) { 
     static char *strings[] = { "\\pagesetup{}", "\\tabsize()", "\\title{}", "\\author{}", "\\date{}"}; 
     return strings[indexOfProperty]; 
    } 

    /* Checks for all possible errors in document properties */ 
    void dealWithDocPropertyErrors() { 
     for (int i = 0; i < sizeof(docPropertyCounters)/sizeof(docPropertyCounters[0]); i++) { 
      if (docPropertyCounters[i] < 1) 
       /* yyerror() is not used in this function because the line number does not need to be shown */ 
       fprintf(stderr, "SYNTAX ERROR: Your source file does not contain the required document property %s", stringFromDocPropertyEnum(i)); 
      else if (docPropertyCounters[i] > 1) 
       fprintf(stderr, "SYNTAX ERROR: Your source file contains more than one instance of the document property %s", stringFromDocPropertyEnum(i)); 
     } 
     exit(-1); 
    } 

    /* Returns the string it takes as an argument excluding the first and last characters */ 
    char* removeFirstAndLastChar(char* string) { 
     string = string + 1; // Removes the first character 
     int i = 0; 
     for (; string[i] != '\0'; i++); 
     string[i - 1] = '\0'; 
     return string; 
    } 
%} 

%union { 
    int iValue;  /* integer value */ 
    char* sValue; /* C-String */ 
}; 

%error-verbose /* sometimes provides better error reporting. Useful sometimes when debugging */ 

%start file /* defining the start condition */ 

%token BSLASH LBRACE RBRACE LPAREN RPAREN COMMA 

%token BEGIN_ END DOCUMENT /* BEGIN seems to be a reserved word so BEGIN_ was used instead */ 

%token PAGESETUP TABSIZE TITLE AUTHOR DATE 

%token <iValue> INTEGER 

%token <sValue> DDMMYYYYDATE STRING 

%% 

file: beginDocument docProperties endDocument 
      { 
       fprintf(yyout, "Message"); 
       dealWithDocPropertyErrors(); 
      } 
      | /* An empty document is parsed to an empty document, no errors generated */ 
      ; 

beginDocument: BSLASH BEGIN_ LBRACE DOCUMENT RBRACE; 

docProperties: docProperties docProperty 
       | /* empty */ 
       ;     

    /* required properties... there should be one instance of each in the input file */ 
docProperty: pageSetupProperty { docPropertyCounters[PAGE_SETUP]++; } 
       | tabSizeProperty { docPropertyCounters[TAB_SIZE]++; } 
       | titleProperty { docPropertyCounters[DOC_TITLE]++; } 
       | authorProperty { docPropertyCounters[DOC_AUTHOR]++; } 
       | dateProperty { docPropertyCounters[DOC_DATE]++; } 
       ; 

pageSetupProperty: BSLASH PAGESETUP LBRACE INTEGER COMMA INTEGER RBRACE 
        { 
         linesPerPage = $4; 
         charsPerLine = $6; 
        } 
        ; 

tabSizeProperty: BSLASH TABSIZE LPAREN INTEGER RPAREN 
       { 
        tabSize = $4; 
       } 
       ; 

titleProperty: BSLASH TITLE LBRACE STRING RBRACE 
       { 
        /* $4 is copied into title excluding the quotation marks at the beginning and end of the string */ 
        title = removeFirstAndLastChar($4); /* $4 is a "pseudo-variable" and can be passed in like this */ 
       } 
       ; 

authorProperty: BSLASH AUTHOR LBRACE STRING RBRACE 
       { 
        author = removeFirstAndLastChar($4); 
       } 
       ; 

dateProperty: BSLASH DATE LBRACE DDMMYYYYDATE RBRACE 
       { 
        date = removeFirstAndLastChar($4); 
       } 
       ; 

endDocument: BSLASH END LBRACE DOCUMENT RBRACE 
      { 
       // Freeing memory created by strdup() 
       free(title); 
       free(author); 
       free(date); 
      } 
      ; 
%% 

int yywrap(void) { 
    return 1; 
} 

void yyerror(const char* str) 
{ 
    fprintf(stderr,"SYNTAX ERROR near line [%d]: %s\n", yylineno, str); 
} 

\begin {document} 

\tabsize(5) 
\pagesetup{30,100 } 
\title{"Why I Love Compiler Design"} 
\author{"COMP421 Student"} 
\date{29/12/2016} 

\end{document} 

私はこの出力を得る:

正確である
Message 

私が期待しているもの。

私はドキュメントプロパティのエラーに対処した後にメッセージを印刷したいと仮定すると、私はメッセージとそれの後に1を出力行の順序を変更する、それは私がそれをすることです:

dealWithDocPropertyErrors(); 
fprintf(yyout, "Message"); 

私は今、同じ入力のための空の出力ファイルを取得します。私はコンパイル中に警告/エラーを受け取りません。

私はWindows 10とFlex 2.5.4aを使用しています。私の.lファイルが以下にあります

%{ 
    #include <stdio.h> 
    #include <stdlib.h> 
    #include <string.h> 
    #include "y.tab.h" 
    void yyerror(const char *); 
    int yylex(void); 
    extern FILE *yyout; /* "Connect" with the output file */ 
    extern int yyparse(); 
%} 
/* %option noyywrap;  Tells flex not to declare the function yywrap() which is only useful in the case of more than 1 input file */ 
    /* Allows printing the line number (of an error) */ 
%option yylineno 
    /* Catches some errors */ 
%option nodefault 
    /* Tells flex not to generate code for the input() and unput() functions which I will not be using */ 
%option nounput 
%option noinput 
    /* Prints the tokens flex recognizes to the console. Useful when debugging and avoids having to write printf() statements for that */ 
%option debug 

%% 

^\\ { return BSLASH; } /* every backslash has to be at the start of a line */ 
\{ { return LBRACE; } 
\} { return RBRACE; } 
\( { return LPAREN; } 
\) { return RPAREN; } 
, { return COMMA; } 

begin { return BEGIN_; } 
end  { return END; } 
document { return DOCUMENT; } 

pagesetup { return PAGESETUP; } 
tabsize { return TABSIZE; } 
title  { return TITLE; } 
author { return AUTHOR; } 
date  { return DATE; } 

(((0[1-9]|[12][0-9]|30)[-/ ]?(0[13-9]|1[012])|31[-/ ]?(0[13578]|1[02])|(0[1-9]|1[0-9]|2[0-8])[-/ ]?02)[-/ ]?[0-9]{4}|29[-/ ]?02[-/ ]?([0-9]{2}(([2468][048]|[02468][48])|[13579][26])|([13579][26]|[02468][048]|0[0-9]|1[0-6])00)) { yylval.sValue = strdup(yytext); return DDMMYYYYDATE; } 
[0-9]*[1-9][0-9]* { yylval.iValue = atoi(strdup(yytext)); return INTEGER; } /* strdup() is string duplicate. yytext must be copied because of its temporary nature */ 
\".*\"    { yylval.sValue = strdup(yytext); return STRING; } 

    /* skip whitespace which is not part of a string. [ \t\r\n]+ is better than [ \t\r\n] performance-wise */ 
[ \t\r\n]+ ; 

    /* anything else is an error */ 
. yyerror("invalid character"); 

%% 

int main(int argc, char *argv[]) { 
    if (argc != 3) 
     yyerror("ERROR You need 2 args: inputFileName outputFileName"); 
    else { 
     yyin = fopen(argv[1], "r"); 
     yyout = fopen(argv[2], "w"); 
     yyparse(); 
     fclose(yyin); 
     fclose(yyout); 
    } 

    return 0; 
} 

答えて

4

これはlex/yaccの問題ではありません。

関数dealWithDocPropertyErrors()は、処理を終了するCライブラリ関数exit()を呼び出し、返さない。

関連する問題