hb2*_*007 3 compiler-construction yacc lex bison flex-lexer
我正在尝试使用 Flex 和 Bison 为简单的格式化语言构建一个编译器。我还处于起步阶段,我已经编写了一些功能。
不过,在这个阶段,我仍然没有将yyout任何东西打印到任何地方。我有一些错误情况,其中输出文件中打印了某些内容,但此输入显然不会发生这种情况。我所有的其他打印语句都将打印到控制台。因此,我希望输出文件将完全为空。但是,当我尝试使用以下内容作为我的输入文件时:
\begin {document}
\tabsize( 5)
\title{"Why I Love Compiler Design"}
\author{"COMP421 Student"}
\date{29/12/2016}
\pagesetup{30,100 }
\end{document}
Run Code Online (Sandbox Code Playgroud)
生成的输出文件为:
有 9 行空行,对应于我在输入文件中的 9 行。然而,我期望的输出只有 1 个空行。
这是我的.l文件:
\begin {document}
\tabsize( 5)
\title{"Why I Love Compiler Design"}
\author{"COMP421 Student"}
\date{29/12/2016}
\pagesetup{30,100 }
\end{document}
Run Code Online (Sandbox Code Playgroud)
这是我的.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;
}
Run Code Online (Sandbox Code Playgroud)
PS:我使用的是 Windows 10 和相当旧版本的 flex (2.5.4a)。
这些行包含回车和/或换行符,\r\n因为您尚未将其放入空白模式。
也许你应该:
[ \t\r\n] ;
Run Code Online (Sandbox Code Playgroud)
您还应该小心在规范中使用C风格的注释。有时这些被视为模式。我总是建议学生只在实际的 C 代码中放置C风格的注释。例如,最好这样做:
[ \t\r\n] ; /* skip whitespace which is not part of a string */
Run Code Online (Sandbox Code Playgroud)
并且永远不要在其他地方发表评论。其他人可能不同意,但我发现它避免了弯曲和野牛的大量悲伤。
PS:我还没有测试我对你的代码的建议......