我目前正在从事一个项目,该项目包括使用 Bison 和 Flex 解析代表机票的文本文件的内容。我创建了两个文件,ticket.y 和 ticket.l,来定义语法规则和相应的正则表达式。
我要分析的示例文件如下(
ExampleAirplaneTicket.txt
):
DOSSIER YBNUKR
ANTOINE/DESAINT-EXUPERY
22/01/16 OS412 CDG 10:00 VIE 12:00 2:00
22/01/16 OS051 VIE 13:20 NRT +07:25 11:05
23/01/16 OS8577 NRT 10:00 CHI 09:00 01:45
这是我的
billet.l
(ticket.l
)文件的内容:
%{
#include "billet.tab.h"
void yyerror(const char *s);
%}
// Define the patterns for digits, alphabetic characters, and separators (spaces or tabs)
DIGIT [0-9]
ALPHA [A-Za-z]
SEP [ \t]
%%
// Define the rules for each token
"DOSSIER" { return DOSSIER; } // Return DOSSIER token when the text "DOSSIER" is matched
{ALPHA}{6} { return CODE_DOSSIER; } // Return CODE_DOSSIER token when exactly 6 alphabetic characters are matched
{ALPHA}+("/"{ALPHA}+)?("-"{ALPHA}+)? { yylval.sval = strdup(yytext); return NOM_PRENOM; } // Return NOM_PRENOM token for names and surnames with optional "/" and "-" separators
{DIGIT}{2}"/"{DIGIT}{2}"/"{DIGIT}{2} { return DATE; } // Return DATE token when a date in the format DD/MM/YY is matched
{ALPHA}{2}{DIGIT}{2,4} { return NUM_VOL; } // Return NUM_VOL token when a flight number (2 alphabetic characters followed by 2 to 4 digits) is matched
{ALPHA}{3} { return CODE_AEROPORT; } // Return CODE_AEROPORT token when a 3-letter airport code is matched
{DIGIT}{2}":"{DIGIT}{2} { return HEURE; } // Return HEURE token when a time in the format HH:MM is matched
"+" { return PLUS; } // Return PLUS token when a plus sign is matched
{DIGIT}{2}":"{DIGIT}{2} { return DUREE_VOL; } // Return DUREE_VOL token when a flight duration in the format HH:MM is matched
{SEP}+ { /*ignore spaces and tabs*/ } // Ignore spaces and tabs
\n { return NEWLINE; } // Return NEWLINE token when a newline character is matched
. { fprintf(stderr, "Caractère non autorisé: '%s'\n", yytext); exit(1); } // Catch any unrecognized characters and print an error message
%%
这是我的
billet.y
(ticket.y
)文件的内容:
%{
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void yyerror(const char *s);
int yylex();
%}
%union {
char *sval;
}
%token DOSSIER CODE_DOSSIER NEWLINE PLUS
%token <sval> DATE NUM_VOL CODE_AEROPORT HEURE DUREE_VOL
%token <sval> NOM_PRENOM
%type <sval> nom_prenom
%type <sval> heure_arrivee
%type <sval> heure_avec_plus
%%
// Start rule: billet
billet: DOSSIER CODE_DOSSIER NEWLINE infos_passager NEWLINE vols;
// Rule to match passenger information
infos_passager: nom_prenom '/' nom_prenom NEWLINE { printf("Infos passager : %s / %s\n", $1, $3); };
// Rule to match multiple flight entries
vols: vol NEWLINE vols | vol NEWLINE;
// Rule to match a single flight entry
vol: DATE NUM_VOL CODE_AEROPORT HEURE CODE_AEROPORT heure_arrivee DUREE_VOL { printf("Vol : %s %s %s %s %s %s %s\n", $1, $2, $3, $4, $5, $6, $7); };
// Rule to match arrival hour, either with or without a plus sign
heure_arrivee: heure_avec_plus | HEURE;
// Rule to match arrival hour with a plus sign
heure_avec_plus: PLUS HEURE { $$ = $2; };
// Rule to match name and surname tokens
nom_prenom: NOM_PRENOM;
%%
// Main function to start parsing
int main() {
yyparse();
return 0;
}
// Error handling function
void yyerror(const char *s) {
fprintf(stderr, "Erreur de syntaxe : %s\n", s);
}
当我编译所有东西时,我无法在
ExampleAirplaneTicket.txt
文件上测试我的程序。
我只是有一个语法错误,尽管进行了多次尝试,但我仍无法解决这些问题,甚至无法弄清楚它的来源。
我正在寻求帮助来理解和解决这些问题。如果您对如何解决这些错误有任何建议或意见,我将不胜感激。
我尝试使用 Flex 和 Bison 实现一个解析器来解析表示机票信息的特定文本格式。我编写了 .l 和 .y 文件,并根据之前的问题进行了必要的调整。现在我希望程序能够成功编译并解析文件 ExampleAirlineTicket.txt 而不会出现任何语法错误或其他问题。除了当我测试文件时我只是得到一个语法错误,但不知道它来自哪里。
当我编译
billet.l
时,我收到这个警告(我认为这不是问题):
billet.l:17: warning, the rule can't match
billet.l:20: warning, the rule can't match
我编译
billet.y
时没有警告,当我用gcc编译所有东西时也没有。
但是当我使用 txt 文件进行测试时,我得到了这个:
Syntax error
来自 flex 的以下警告:
billet.l:17: warning, the rule can't match
billet.l:20: warning, the rule can't match
来自以下规则:
NOM_PRENOM
涵盖了CODE_AEROPORT
HEURE
令牌与DUREE_VOL
所以,一些标记(
CODE_AEROPORT
和DUREE_VOL
)永远不会出现。这可能是您收到默认“语法错误”消息的原因。
注意:bison生成的C源文件显示,当上报的token数(yycount内部变量)为0时,报“Syntax error”:
/*
[...]
- The only way there can be no lookahead present (in yychar) is if
this state is a consistent state with a default action. Thus,
detecting the absence of a lookahead is sufficient to determine
that there is no unexpected or expected token to report. In that
case, just report a simple "syntax error".
[...]
*/
[...]
switch (yycount)
{
# define YYCASE_(N, S) \
case N: \
yyformat = S; \
break
YYCASE_(0, YY_("syntax error"));
YYCASE_(1, YY_("syntax error, unexpected %s"));
YYCASE_(2, YY_("syntax error, unexpected %s, expecting %s"));
YYCASE_(3, YY_("syntax error, unexpected %s, expecting %s or %s"));
YYCASE_(4, YY_("syntax error, unexpected %s, expecting %s or %s or %s"));
YYCASE_(5, YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s"));
# undef YYCASE_
}