Flex와 Bison을 사용하여 간단한 형식 지정 언어 용 컴파일러를 작성하려고합니다. 나는 아직 시작 단계에 있으며 일부 기능을 코딩했습니다.Bison (Yacc)이 이유없이 새로운 줄을 인쇄하는 이유는 무엇입니까?
아직이 단계에서는 어디에도 yyout을 인쇄하지 않았습니다. 출력 파일에 무언가가 인쇄되는 오류 케이스가 있는데,이 입력에서는 분명히 발생하지 않습니다. 다른 모든 인쇄 명령문은 콘솔에 인쇄됩니다. 그래서 출력 파일이 완전히 비어있을 것으로 예상됩니다.
이\begin {document}
\tabsize(5)
\title{"Why I Love Compiler Design"}
\author{"COMP421 Student"}
\date{29/12/2016}
\pagesetup{30,100 }
\end{document}
생성 된 출력 파일은 다음과 같습니다 : 9 개 빈 줄이 있습니다
, 내가에 있던 9 개 라인에 해당하는 그러나, 나는 내 입력 파일로 다음을 사용하려고 내 입력 파일. 그러나 예상 한 결과는 빈 줄 하나뿐입니다.
이 내 .L 파일입니다
%{
#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;
/* 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 an integer and returns the corresponding document property as a string. The order is based on the enum. */
static inline char *stringFromDocPropertyEnum(document_property indexOfProperty) {
static char *strings[] = { "\\pagesetup{}", "\\tabsize()", "\\title{}", "\\author{}", "\\date{}"};
return strings[indexOfProperty];
}
%}
%union {
int iValue; /* integer value */
char* sValue; /* C-String */
};
%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
{
/* Checks for all possible errors in document properties */
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));
}
| /* 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;
tabSizeProperty: BSLASH TABSIZE LPAREN INTEGER RPAREN;
titleProperty: BSLASH TITLE LBRACE STRING RBRACE;
authorProperty: BSLASH AUTHOR LBRACE STRING RBRACE;
dateProperty: BSLASH DATE LBRACE DDMMYYYYDATE RBRACE;
endDocument: BSLASH END LBRACE DOCUMENT RBRACE;
%%
int yywrap(void) {
return 1;
}
void yyerror(const char* str)
{
fprintf(stderr,"SYNTAX ERROR near line [%d]: %s\n",yylineno, str);
}
PS : 나는 윈도우 10와 플렉스의 아주 오래된 버전을 사용하고 있습니다 (2.5.4a이 내 .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 yyparse();
%}
/* Allows printing the line number (of an error) */
%option yylineno
%%
^\\ { printf("LEX returned token BSLASH\n"); return BSLASH; } /* every backslash has to be at the start of a line */
\{ { printf("LEX returned token LBRACE\n"); return LBRACE; }
\} { printf("LEX returned token RBRACE\n"); return RBRACE; }
\( { printf("LEX returned token LPAREN\n"); return LPAREN; }
\) { printf("LEX returned token RPAREN\n"); return RPAREN; }
, { printf("LEX returned token COMMA\n"); return COMMA; }
begin { printf("LEX returned token BEGIN_\n"); return BEGIN_; } /* Note the use of \ in this and other regex expressions to escape the following symbols: \, {, }, (,), */
end { printf("LEX returned token END\n"); return END; }
document { printf("LEX returned token DOCUMENT\n"); return DOCUMENT; }
pagesetup { printf("LEX returned token PAGESETUP\n"); return PAGESETUP; }
tabsize { printf("LEX returned token TABSIZE\n"); return TABSIZE; }
title { printf("LEX returned token TITLE\n"); return TITLE; }
author { printf("LEX returned token AUTHOR\n"); return AUTHOR; }
date { printf("LEX returned token DATE\n"); 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)) { printf("LEX returned token DDMMYYYYDATE\n"); yylval.sValue = yytext; return DDMMYYYYDATE; }
[0-9]*[1-9][0-9]* { printf("LEX returned token INTEGER\n"); yylval.iValue = atoi(yytext); return INTEGER; }
\".*\" { printf("LEX returned token STRING\n"); yylval.sValue = yytext; return STRING; }
/* skip whitespace which is not part of a string */
[ \t] ;
/* 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;
}
입니다
).
그것은하지 않습니다 .... 코드에 내 제안을 테스트하지 않았습니다. 이것은 당신이 사용하고있는 * lex * 또는 * flex *에 의해 수행됩니다. – EJP