spot/spot/parseaut/scanaut.ll
Alexandre Duret-Lutz ac6b0c9432 include config.h in all *.cc files
This helps working around missing C functions like strcasecmp that do
not exist everywhere (e.g. on Cygwin), and for which lib/ supplies a
replacement.  Unfortunately we do not have such build in our current
continuous integration suite, so we cannot easily detect files where
such config.h inclusion would be useful.  Therefore this patch simply
makes it mandatory to include config.h in *.cc files.  Including this
in public *.hh file is currently forbidden.

* spot/gen/automata.cc, spot/gen/formulas.cc,
spot/kripke/fairkripke.cc, spot/kripke/kripke.cc,
spot/ltsmin/ltsmin.cc, spot/misc/game.cc, spot/parseaut/fmterror.cc,
spot/parsetl/fmterror.cc, spot/parsetl/parsetl.yy,
spot/priv/bddalloc.cc, spot/priv/freelist.cc, spot/priv/satcommon.cc,
spot/priv/trim.cc, spot/priv/weight.cc, spot/ta/ta.cc,
spot/ta/taexplicit.cc, spot/ta/taproduct.cc, spot/ta/tgtaexplicit.cc,
spot/ta/tgtaproduct.cc, spot/taalgos/dot.cc,
spot/taalgos/emptinessta.cc, spot/taalgos/minimize.cc,
spot/taalgos/reachiter.cc, spot/taalgos/statessetbuilder.cc,
spot/taalgos/stats.cc, spot/taalgos/tgba2ta.cc, spot/tl/apcollect.cc,
spot/tl/contain.cc, spot/tl/declenv.cc, spot/tl/defaultenv.cc,
spot/tl/dot.cc, spot/tl/exclusive.cc, spot/tl/hierarchy.cc,
spot/tl/length.cc, spot/tl/ltlf.cc, spot/tl/mark.cc,
spot/tl/mutation.cc, spot/tl/nenoform.cc, spot/tl/print.cc,
spot/tl/randomltl.cc, spot/tl/relabel.cc, spot/tl/remove_x.cc,
spot/tl/simplify.cc, spot/tl/snf.cc, spot/tl/unabbrev.cc,
spot/twa/acc.cc, spot/twa/bdddict.cc, spot/twa/bddprint.cc,
spot/twa/formula2bdd.cc, spot/twa/taatgba.cc, spot/twa/twa.cc,
spot/twa/twagraph.cc, spot/twa/twaproduct.cc, spot/twaalgos/aiger.cc,
spot/twaalgos/alternation.cc, spot/twaalgos/are_isomorphic.cc,
spot/twaalgos/bfssteps.cc, spot/twaalgos/canonicalize.cc,
spot/twaalgos/cleanacc.cc, spot/twaalgos/cobuchi.cc,
spot/twaalgos/complement.cc, spot/twaalgos/complete.cc,
spot/twaalgos/compsusp.cc, spot/twaalgos/couvreurnew.cc,
spot/twaalgos/cycles.cc, spot/twaalgos/degen.cc,
spot/twaalgos/determinize.cc, spot/twaalgos/dot.cc,
spot/twaalgos/dtbasat.cc, spot/twaalgos/dtwasat.cc,
spot/twaalgos/dualize.cc, spot/twaalgos/emptiness.cc,
spot/twaalgos/gtec/ce.cc, spot/twaalgos/gtec/gtec.cc,
spot/twaalgos/gtec/sccstack.cc, spot/twaalgos/gtec/status.cc,
spot/twaalgos/gv04.cc, spot/twaalgos/hoa.cc,
spot/twaalgos/iscolored.cc, spot/twaalgos/isdet.cc,
spot/twaalgos/isunamb.cc, spot/twaalgos/isweakscc.cc,
spot/twaalgos/langmap.cc, spot/twaalgos/lbtt.cc,
spot/twaalgos/ltl2taa.cc, spot/twaalgos/ltl2tgba_fm.cc,
spot/twaalgos/magic.cc, spot/twaalgos/mask.cc,
spot/twaalgos/minimize.cc, spot/twaalgos/neverclaim.cc,
spot/twaalgos/parity.cc, spot/twaalgos/postproc.cc,
spot/twaalgos/powerset.cc, spot/twaalgos/product.cc,
spot/twaalgos/rabin2parity.cc, spot/twaalgos/randomgraph.cc,
spot/twaalgos/randomize.cc, spot/twaalgos/reachiter.cc,
spot/twaalgos/relabel.cc, spot/twaalgos/remfin.cc,
spot/twaalgos/remprop.cc, spot/twaalgos/sbacc.cc,
spot/twaalgos/sccfilter.cc, spot/twaalgos/sccinfo.cc,
spot/twaalgos/se05.cc, spot/twaalgos/sepsets.cc,
spot/twaalgos/simulation.cc, spot/twaalgos/split.cc,
spot/twaalgos/stats.cc, spot/twaalgos/strength.cc,
spot/twaalgos/stripacc.cc, spot/twaalgos/stutter.cc,
spot/twaalgos/sum.cc, spot/twaalgos/tau03.cc,
spot/twaalgos/tau03opt.cc, spot/twaalgos/totgba.cc,
spot/twaalgos/toweak.cc, spot/twaalgos/translate.cc,
spot/twaalgos/word.cc, tests/core/acc.cc, tests/core/bitvect.cc,
tests/core/checkpsl.cc, tests/core/checkta.cc, tests/core/consterm.cc,
tests/core/emptchk.cc, tests/core/equalsf.cc, tests/core/graph.cc,
tests/core/ikwiad.cc, tests/core/intvcmp2.cc, tests/core/intvcomp.cc,
tests/core/kind.cc, tests/core/kripkecat.cc, tests/core/length.cc,
tests/core/ltlrel.cc, tests/core/ngraph.cc, tests/core/parity.cc,
tests/core/randtgba.cc, tests/core/readltl.cc, tests/core/reduc.cc,
tests/core/safra.cc, tests/core/sccif.cc, tests/core/syntimpl.cc,
tests/core/taatgba.cc, tests/core/tostring.cc, tests/core/trival.cc,
tests/core/twagraph.cc, tests/ltsmin/modelcheck.cc,
spot/parseaut/scanaut.ll, spot/parsetl/scantl.ll: Include config.h.
* spot/gen/Makefile.am, spot/graph/Makefile.am,
spot/kripke/Makefile.am, spot/ltsmin/Makefile.am,
spot/parseaut/Makefile.am, spot/parsetl/Makefile.am,
spot/priv/Makefile.am, spot/ta/Makefile.am, spot/taalgos/Makefile.am,
spot/tl/Makefile.am, spot/twa/Makefile.am, spot/twaalgos/Makefile.am,
spot/twaalgos/gtec/Makefile.am, tests/Makefile.am: Add the -I lib/
flags.
* tests/sanity/includes.test: Catch missing config.h in *.cc, and
diagnose config.h in *.hh.
* tests/sanity/style.test: Better diagnostics.
2018-02-21 17:59:09 +01:00

495 lines
13 KiB
LLVM

/* -*- coding: utf-8 -*-
** Copyright (C) 2014-2018 Laboratoire de Recherche et Développement
** de l'Epita (LRDE).
**
** This file is part of Spot, a model checking library.
**
** Spot is free software; you can redistribute it and/or modify it
** under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 3 of the License, or
** (at your option) any later version.
**
** Spot is distributed in the hope that it will be useful, but WITHOUT
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
** or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
** License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
%option noyywrap
%option prefix="hoayy"
%option outfile="lex.yy.c"
%option reentrant
%option extra-type="struct extra_data*"
/* %option debug */
%top{
#include "config.h"
}
%{
#include <string>
#include <sys/stat.h>
#include <spot/parseaut/parsedecl.hh>
#include "spot/priv/trim.hh"
#define YY_USER_ACTION yylloc->columns(yyleng);
typedef hoayy::parser::token token;
struct extra_data
{
unsigned comment_level = 0;
unsigned parent_level = 0;
int orig_cond = 0;
bool lbtt_s = false;
bool lbtt_t = false;
unsigned lbtt_states = 0;
bool yyin_close = true;
};
%}
eol \n+|\r+
eol2 (\n\r)+|(\r\n)+
eols ({eol}|{eol2})*
identifier [[:alpha:]_][[:alnum:]_.-]*
%x in_COMMENT in_STRING in_NEVER_PAR
%s in_HOA in_NEVER in_LBTT_HEADER
%s in_LBTT_STATE in_LBTT_INIT in_LBTT_TRANS
%s in_LBTT_T_ACC in_LBTT_S_ACC in_LBTT_GUARD
%s in_DSTAR
%%
%{
std::string s;
yylloc->step();
auto parse_int = [&](){
errno = 0;
char* end;
unsigned long n = strtoul(yytext, &end, 10);
yylval->num = n;
if (errno || yylval->num != n)
{
error_list.push_back(spot::parse_aut_error(*yylloc, "value too large"));
yylval->num = 0;
}
return end;
};
%}
/* skip blanks and comments */
{eol} yylloc->lines(yyleng); yylloc->step();
{eol2} yylloc->lines(yyleng / 2); yylloc->step();
[ \t\v\f]+ yylloc->step();
"/*" {
yyextra->orig_cond = YY_START;
BEGIN(in_COMMENT);
yyextra->comment_level = 1;
}
<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;
<INITIAL>"DSA" BEGIN(in_DSTAR); return token::DSA;
<INITIAL>"DRA" BEGIN(in_DSTAR); return token::DRA;
<INITIAL>[0-9]+[ \t][0-9]+[ts]? {
BEGIN(in_LBTT_HEADER);
char* end = nullptr;
errno = 0;
unsigned long n = strtoul(yytext, &end, 10);
yylval->num = n;
unsigned s = end - yytext;
yylloc->end = yylloc->begin;
yylloc->end.columns(s);
yyless(s);
if (errno || yylval->num != n)
{
error_list.push_back(
spot::parse_aut_error(*yylloc,
"value too large"));
yylval->num = 0;
}
yyextra->lbtt_states = yylval->num;
return token::LBTT;
}
<in_HOA>{
"States:" return token::STATES;
"Start:" return token::START;
"AP:" return token::AP;
"Alias:" return token::ALIAS;
"Acceptance:" return token::ACCEPTANCE;
"acc-name:" return token::ACCNAME;
"tool:" return token::TOOL;
"name:" return token::NAME;
"properties:" return token::PROPERTIES;
"spot.highlight.states:" return token::SPOT_HIGHLIGHT_STATES;
"spot.highlight.edges:" return token::SPOT_HIGHLIGHT_EDGES;
"--BODY--" return token::BODY;
"--END--" BEGIN(INITIAL); return token::END;
"State:" return token::STATE;
[tf{}()\[\]&|!] return *yytext;
{identifier} {
yylval->str = new std::string(yytext, yyleng);
return token::IDENTIFIER;
}
{identifier}":" {
yylval->str = new std::string(yytext, yyleng - 1);
return token::HEADERNAME;
}
"@"[[:alnum:]_.-]+ {
yylval->str = new std::string(yytext + 1, yyleng - 1);
return token::ANAME;
}
[0-9]+ parse_int(); return token::INT;
}
<in_DSTAR>{
"States:" return token::STATES;
"State:" return token::STATE;
"Start:" return token::START;
"AP:" return token::AP;
"v2" return token::V2;
"explicit" return token::EXPLICIT;
"Comment:".* yylloc->step();
"//".* yylloc->step();
"Acceptance-Pairs:" return token::ACCPAIRS;
"Acc-Sig:" return token::ACCSIG;
"---" return token::ENDOFHEADER;
[0-9]+ parse_int(); return token::INT;
/* The start of any automaton is the end of this one.
We do not try to detect LBTT automata, as that would
be too hard to distinguish from state numbers. */
{eols}("HOA:"|"never"|"DSA"|"DRA") {
yylloc->end = yylloc->begin;
yyless(0);
BEGIN(INITIAL);
return token::ENDDSTAR;
}
<<EOF>> return token::ENDDSTAR;
}
<in_NEVER>{
"skip" return token::SKIP;
"if" return token::IF;
"fi" return token::FI;
"do" return token::DO;
"od" return token::OD;
"->" return token::ARROW;
"goto" return token::GOTO;
"false"|"0" return token::FALSE;
"atomic" return token::ATOMIC;
"assert" return token::ASSERT;
("!"[ \t]*)?"(" {
yyextra->parent_level = 1;
BEGIN(in_NEVER_PAR);
yylval->str = new std::string(yytext, yyleng);
}
"true"|"1" {
yylval->str = new std::string(yytext, yyleng);
return token::FORMULA;
}
[a-zA-Z][a-zA-Z0-9_]* {
yylval->str = new std::string(yytext, yyleng);
return token::IDENTIFIER;
}
}
/* Note: the LBTT format is scanf friendly, but not Bison-friendly.
If we only tokenize it as a stream of INTs, the parser will have
a very hard time recognizing what is a state from what is a
transitions. As a consequence we abuse the start conditions to
maintain a state an return integers with different semantic types
depending on the purpose of those integers. */
<in_LBTT_HEADER>{
[0-9]+[st]* {
BEGIN(in_LBTT_STATE);
auto end = parse_int();
yyextra->lbtt_s = false;
yyextra->lbtt_t = false;
if (end)
while (int c = *end++)
{
if (c == 's')
yyextra->lbtt_s = true;
else // c == 't'
yyextra->lbtt_t = true;
}
if (!yyextra->lbtt_t)
yyextra->lbtt_s = true;
if (yyextra->lbtt_states == 0)
{
BEGIN(INITIAL);
return token::LBTT_EMPTY;
}
if (yyextra->lbtt_s && !yyextra->lbtt_t)
return token::INT_S;
else
return token::INT;
}
}
<in_LBTT_STATE>[0-9]+ {
parse_int();
BEGIN(in_LBTT_INIT);
return token::STATE_NUM;
}
<in_LBTT_INIT>[01] {
yylval->num = *yytext - '0';
if (yyextra->lbtt_s)
BEGIN(in_LBTT_S_ACC);
else
BEGIN(in_LBTT_TRANS);
return token::INT;
}
<in_LBTT_S_ACC>{
[0-9]+ parse_int(); return token::ACC;
"-1" BEGIN(in_LBTT_TRANS); yylloc->step();
}
<in_LBTT_TRANS>{
[0-9]+ {
parse_int();
if (yyextra->lbtt_t)
BEGIN(in_LBTT_T_ACC);
else
BEGIN(in_LBTT_GUARD);
return token::DEST_NUM;
}
"-1" {
if (--yyextra->lbtt_states)
{
BEGIN(in_LBTT_STATE);
yylloc->step();
}
else
{
BEGIN(INITIAL);
return token::ENDAUT;
}
}
}
<in_LBTT_T_ACC>{
[0-9]+ parse_int(); return token::ACC;
"-1" BEGIN(in_LBTT_GUARD); yylloc->step();
}
<in_LBTT_GUARD>{
[^\n\r]* {
yylval->str = new std::string(yytext, yyleng);
BEGIN(in_LBTT_TRANS);
return token::STRING;
}
}
<in_COMMENT>{
"/*" ++yyextra->comment_level;
[^*/\n\r]* continue;
"/"[^*\n\r]* continue;
"*" continue;
{eol} yylloc->lines(yyleng); yylloc->end.column = 1;
{eol2} yylloc->lines(yyleng / 2); yylloc->end.column = 1;
"*/" {
if (--yyextra->comment_level == 0)
{
yylloc->step();
int oc = yyextra->orig_cond;
BEGIN(oc);
}
}
<<EOF>> {
int oc = yyextra->orig_cond;
BEGIN(oc);
error_list.push_back(
spot::parse_aut_error(*yylloc,
"unclosed comment"));
return 0;
}
}
/* matched late, so that the in_LBTT_GUARD pattern has precedence */
"\"" {
yyextra->orig_cond = YY_START;
BEGIN(in_STRING);
yyextra->comment_level = 1;
}
<in_STRING>{
\" {
int oc = yyextra->orig_cond;
BEGIN(oc);
yylval->str = new std::string(s);
return token::STRING;
}
{eol} {
s.append(yytext, yyleng);
yylloc->lines(yyleng); yylloc->end.column = 1;
}
{eol2} {
s.append(yytext, yyleng);
yylloc->lines(yyleng / 2); yylloc->end.column = 1;
}
\\. s += yytext[1];
[^\\\"\n\r]+ s.append(yytext, yyleng);
<<EOF>> {
error_list.push_back(
spot::parse_aut_error(*yylloc,
"unclosed string"));
int oc = yyextra->orig_cond;
BEGIN(oc);
yylval->str = new std::string(s);
return token::STRING;
}
}
<in_NEVER_PAR>{
"(" {
++yyextra->parent_level;
yylval->str->append(yytext, yyleng);
}
/* if we match ")&&(" or ")||(", stay in <in_NEVER_PAR> mode */
")"[ \t]*("&&"|"||")[ \t!]*"(" {
yylval->str->append(yytext, yyleng);
}
")" {
yylval->str->append(yytext, yyleng);
if (!--yyextra->parent_level)
{
BEGIN(in_NEVER);
spot::trim(*yylval->str);
return token::FORMULA;
}
}
{eol} {
yylval->str->append(yytext, yyleng);
yylloc->lines(yyleng); yylloc->end.column = 1;
}
{eol2} {
yylval->str->append(yytext, yyleng);
yylloc->lines(yyleng / 2); yylloc->end.column = 1;
}
[^()\n\r]+ yylval->str->append(yytext, yyleng);
<<EOF>> {
error_list.push_back(
spot::parse_aut_error(*yylloc,
"missing closing parenthese"));
yylval->str->append(yyextra->parent_level, ')');
BEGIN(in_NEVER);
spot::trim(*yylval->str);
return token::FORMULA;
}
}
. return *yytext;
%{
/* Dummy use of yyunput to shut up a gcc warning. */
(void) &yyunput;
%}
%%
namespace spot
{
void
hoayyreset(yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
BEGIN(INITIAL);
yyextra->comment_level = 0;
yyextra->parent_level = 0;
}
int
hoayyopen(const std::string &name, yyscan_t* scanner)
{
yylex_init_extra(new extra_data, scanner);
yyscan_t yyscanner = *scanner;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
bool want_interactive = false;
// yy_flex_debug = 1;
if (name == "-")
{
// If the input is a pipe, make the scanner
// interactive so that it does not wait for the input
// buffer to be full to process automata.
struct stat s;
if (fstat(fileno(stdin), &s) < 0)
throw std::runtime_error("fstat failed");
if (S_ISFIFO(s.st_mode))
want_interactive = true;
yyin = stdin;
yyextra->yyin_close = false;
}
else
{
yyin = fopen(name.c_str(), "r");
if (!yyin)
return 1;
yyextra->yyin_close = true;
}
if (want_interactive)
yy_set_interactive(1);
return 0;
}
int
hoayystring(const char* data, yyscan_t* scanner)
{
yylex_init_extra(new extra_data, scanner);
yy_scan_string(data, *scanner);
return 0;
}
int
hoayyopen(int fd, yyscan_t* scanner)
{
yylex_init_extra(new extra_data, scanner);
yyscan_t yyscanner = *scanner;
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
bool want_interactive = false;
yyextra->yyin_close = false;
yyin = fdopen(fd, "r");
if (!yyin)
throw std::runtime_error("fdopen failed");
// If the input is a pipe, make the scanner
// interactive so that it does not wait for the input
// buffer to be full to process automata.
struct stat s;
if (fstat(fd, &s) < 0)
throw std::runtime_error("fstat failed");
if (S_ISFIFO(s.st_mode))
want_interactive = true;
if (want_interactive)
yy_set_interactive(1);
return 0;
}
void
hoayyclose(yyscan_t yyscanner)
{
struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
if (yyin)
{
if (yyextra->yyin_close)
fclose(yyin);
yyin = NULL;
}
delete yyextra;
yylex_destroy(yyscanner);
}
}