parse_aut: add support for #line

Fixes issue #232.

* spot/parseaut/parseaut.yy, spot/parseaut/public.hh,
spot/parseaut/scanaut.ll: Add support for #line.
* tests/core/parseaut.test: Test it.
* NEWS: Mention it.
This commit is contained in:
Alexandre Duret-Lutz 2021-04-16 18:04:41 +02:00
parent 093de290c1
commit 803a61a03d
5 changed files with 63 additions and 16 deletions

View file

@ -255,6 +255,7 @@ extern "C" int strverscmp(const char *s1, const char *s2);
%token ACCPAIRS "Acceptance-Pairs:"
%token ACCSIG "Acc-Sig:";
%token ENDOFHEADER "---";
%token <str> LINEDIRECTIVE "#line"
%left '|'
@ -338,6 +339,10 @@ extern "C" int strverscmp(const char *s1, const char *s2);
%%
aut: aut-1 { res.h->loc = @$; YYACCEPT; }
/* Not how we do not accept garbage before LINEDIRECTIVE. This is because
all error will be relative to the specified filename, so that filename
must not be changed after any error was reported. */
| LINEDIRECTIVE { res.h->filename = *$1; } aut
| ENDOFFILE { YYABORT; }
| error ENDOFFILE { YYABORT; }
| error aut-1
@ -2635,6 +2640,7 @@ namespace spot
check_version(r);
last_loc = r.h->loc;
last_loc.step();
filename_ = r.h->filename; // in case it was changed
if (r.h->aborted)
{
if (opts_.ignore_abort)

View file

@ -69,7 +69,7 @@ namespace spot
/// Format of the automaton.
parsed_aut_type type = parsed_aut_type::Unknown;
/// Name of the stream (used for displaying syntax errors)
const std::string filename;
std::string filename;
/// \brief Syntax errors that occurred during parsing.
///
/// Note that the parser does not print any diagnostic.

View file

@ -1,5 +1,5 @@
/* -*- coding: utf-8 -*-
** Copyright (C) 2014-2018, 2020 Laboratoire de Recherche et Développement
** Copyright (C) 2014-2018, 2020, 2021 Laboratoire de Recherche et Développement
** de l'Epita (LRDE).
**
** This file is part of Spot, a model checking library.
@ -90,6 +90,27 @@ identifier [[:alpha:]_][[:alnum:]_.-]*
BEGIN(in_COMMENT);
yyextra->comment_level = 1;
}
<INITIAL>"#line"[ \t]+[0-9]+[ \t]+\"[^\"\n]*\" {
errno = 0;
char* end;
unsigned long n = strtoul(yytext + 5, &end, 10);
yylval->num = n;
if (errno || yylval->num != n)
{
error_list.push_back(spot::parse_aut_error(*yylloc, "value too large")); }
else if (error_list.empty())
{
char* beg = strchr(end, '"');
end = strrchr(beg + 1, '"');
yylval->str = new std::string(beg + 1, end);
yylloc->initialize(nullptr, n - 1, yylloc->begin.column);
return token::LINEDIRECTIVE;
}
else
{
error_list.push_back(spot::parse_aut_error(*yylloc, "#line may not occur after any error"));
}
}
<INITIAL>"HOA:" BEGIN(in_HOA); return token::HOA;
<INITIAL,in_HOA>"--ABORT--" BEGIN(INITIAL); throw spot::hoa_abort{*yylloc};
<INITIAL>"never" BEGIN(in_NEVER); return token::NEVER;