Compiler construction 为什么Bison(Yacc)毫无理由地打印新行?

Compiler construction 为什么Bison(Yacc)毫无理由地打印新行?,compiler-construction,bison,flex-lexer,yacc,lex,Compiler Construction,Bison,Flex Lexer,Yacc,Lex,我正在尝试使用Flex和Bison为一种简单的格式化语言构建一个编译器。我还处于开始阶段,我已经编写了一些功能 但是在这个阶段,我仍然没有在任何地方打印任何东西。我有一些错误案例,其中输出文件中打印了一些内容,但这种输入显然不会发生。我的所有其他打印语句都将打印到控制台。因此,我希望输出文件将完全为空。但是,当我尝试使用以下内容作为输入文件时: \begin {document} \tabsize( 5) \title{"Why I Love Compiler Design"} \author

我正在尝试使用Flex和Bison为一种简单的格式化语言构建一个编译器。我还处于开始阶段,我已经编写了一些功能

但是在这个阶段,我仍然没有在任何地方打印任何东西。我有一些错误案例,其中输出文件中打印了一些内容,但这种输入显然不会发生。我的所有其他打印语句都将打印到控制台。因此,我希望输出文件将完全为空。但是,当我尝试使用以下内容作为输入文件时:

\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
文件:

%{
#包括
#包括
#包括
#包括“y.tab.h”
无效错误(常量字符*);
int yylex(无效);
/*“连接”输出文件*/
外部文件*yyout;
extern int yyparse();
%}
/*允许打印行号(错误)*/
%选项yylineno
%%
^\\{printf(“LEX returned token BSLASH\n”);return BSLASH;}/*每个反斜杠必须位于一行的开头*/
\{{printf(“LEX返回标记LBRACE\n”);返回LBRACE;}
\}{printf(“LEX返回标记RBRACE\n”);返回RBRACE;}
\({printf(“LEX返回标记LPAREN\n”);返回LPAREN;}
\){printf(“LEX返回的令牌RPAREN\n”);返回RPAREN;}
,{printf(“LEX返回的标记逗号”);返回逗号;}
begin{printf(“LEX返回的令牌begin\n”);return begin\u;}/*注意在这个和其他正则表达式中使用\来转义以下符号:\,{,},(,)*/
end{printf(“LEX返回的令牌end\n”);return end;}
文档{printf(“LEX返回的令牌文档”\n”);返回文档;}
pagesetup{printf(“LEX返回的令牌pagesetup\n”);返回pagesetup;}
tabsize{printf(“LEX返回的令牌tabsize\n”);返回tabsize;}
title{printf(“LEX返回的令牌title\n”);返回title;}
author{printf(“LEX返回的令牌author\n”);返回author;}
日期{printf(“LEX返回的令牌日期”);返回日期;}
(0[13-9]1[12]0[12-9[1-1-9[1-1-9[1[12[1[1-1-9[1[12[1-9[1-9[1[1-1-9[1[1-9[1-9[1[1-9[1[1[1-9[1[1[1-9[12[12[12[12[12[0[12[0[12[0[12[0[12[0[12[0[0[12[12[12[10[12[9]9]除除除除除除除除除除除除除除除除除12[10[12[12[12[12[12[10[12[12[10[10[10[10[10[1-9[12[10[10[10[10[10[1[1-9]]9]]]]]9]]]9]除除除除除除除除除除除除除除除除除除8]| 0[0-9]| 1[0-6])00{printf(“LEX返回的标记DDMMYYYYDATE\n”);yylval.sValue=yytext;返回DDMMYYYYDATE;}
[0-9]*[1-9][0-9]*{printf(“LEX返回的令牌整数\n”);yylval.iValue=atoi(yytext);返回整数;}
\“*\”{printf(“LEX返回的令牌字符串\n”);yylval.sValue=yytext;返回字符串;}
/*跳过不属于字符串的空白*/
[\t];
/*其他任何东西都是错误的*/
. yyerror(“无效字符”);
%%
int main(int argc,char*argv[]){
如果(argc!=3)
yyerror(“您需要2个参数的错误:inputFileName outputFileName”);
否则{
yyin=fopen(argv[1],“r”);
yyout=fopen(argv[2],“w”);
yyparse();
fclose(yyin);
fclose(yyout);
}
返回0;
}
这是我的
.y
文件:

%{
#包括
#包括
#包括
#包括“y.tab.h”
无效错误(常量字符*);
int yylex(无效);
/*“连接”输出文件*/
外部文件*yyout;
外部内部yylineno;
/*带有计数器的数组,计数器指示5个文档属性中的每个属性在输入文件中出现的次数。属性的顺序在下面的枚举中定义*/
int docproperty计数器[5];
/*具有5个文档属性的枚举列表*/
typedef枚举{页面设置、选项卡大小、文档标题、文档作者、文档日期}文档属性;
/*接受整数并以字符串形式返回相应的文档属性。顺序基于枚举*/
静态内联字符*stringFromDocPropertyEnum(文档属性indexOfProperty){
静态字符*字符串[]={“\\pagesetup{}”、“\\tabsize()”、“\\title{}”、“\\author{}”、“\\date{}”;
返回字符串[indexOfProperty];
}
%}
%联合{
int iValue;/*整数值*/
char*s值;/*C-String*/
}; 
%开始文件/*定义开始条件*/
%令牌BSLASH LBRACE RBRACE LPAREN RPAREN逗号
%令牌BEGIN_uuEND DOCUMENT/*BEGIN似乎是一个保留字,因此改用BEGIN_u*/
%令牌页面设置选项卡大小标题作者日期
%令牌整数
%令牌DDMMYYYYDATE字符串
%%
文件:beginDocument docProperties endDocument
{ 
/*检查文档属性中所有可能的错误*/
对于(int i=0;i1)
fprintf(stderr,“语法错误:源文件包含文档属性%s的多个实例”,stringFromDocPropertyEnum(i));
}
|/*将空文档解析为空文档,不会生成错误*/
;
开始文档:b快速开始\ulbrace文档RBRACE;
docProperties:docProperties docProperty
|/*空*/
;                
/*所需属性。。。在输入文件中,每个都应该有一个实例*/
docProperty:pageSetupProperty{docPropertyCounters[PAGE_SETUP]++;}
|tabSizeProperty{docPropertyCounters[TAB_SIZE]++;}
|标题属性{docPropertyCounters[DOC_TITLE]++;}
|authorProperty{docPropertyCounters[DOC_AUTHOR]++;}
|日期属性{do
[ \t\r\n]      ;
[ \t\r\n]      ;  /* skip whitespace which is not part of a string */