spot/src/ltlvisit/tostring.cc
Alexandre Duret-Lutz 1551c5d947 Upgrade GPL v2+ to GPL v3+.
* NEWS: Mention this.
* COPYING: Replace by GPL v3.
* src/sanity/style.test: Check files with the wrong license,
in case we forgot to update it during a merge.
* Makefile.am, bench/Makefile.am, bench/emptchk/Makefile.am,
bench/emptchk/defs.in, bench/emptchk/ltl-human.sh,
bench/emptchk/ltl-random.sh, bench/emptchk/pml-clserv.sh,
bench/emptchk/pml-eeaean.sh, bench/emptchk/pml2tgba.pl,
bench/ltl2tgba/big, bench/ltl2tgba/defs.in, bench/ltl2tgba/known,
bench/ltl2tgba/lbtt2csv.pl, bench/ltl2tgba/ltl2baw.in,
bench/ltl2tgba/parseout.pl, bench/ltl2tgba/small,
bench/ltlclasses/Makefile.am, bench/ltlclasses/defs.in,
bench/ltlclasses/run, bench/ltlcounter/Makefile.am,
bench/ltlcounter/defs.in, bench/ltlcounter/run,
bench/scc-stats/Makefile.am, bench/scc-stats/stats.cc,
bench/split-product/Makefile.am, bench/split-product/cutscc.cc,
bench/split-product/pml2tgba.pl, bench/wdba/Makefile.am,
bench/wdba/defs.in, bench/wdba/run, configure.ac, doc/Makefile.am,
doc/dot.in, doc/tl/Makefile.am, iface/Makefile.am,
iface/dve2/Makefile.am, iface/dve2/defs.in, iface/dve2/dve2.cc,
iface/dve2/dve2.hh, iface/dve2/dve2check.cc,
iface/dve2/dve2check.test, iface/dve2/finite.test,
iface/dve2/kripke.test, iface/gspn/Makefile.am, iface/gspn/common.cc,
iface/gspn/common.hh, iface/gspn/dcswave.test,
iface/gspn/dcswaveeltl.test, iface/gspn/dcswavefm.test,
iface/gspn/dcswaveltl.test, iface/gspn/dottygspn.cc,
iface/gspn/dottyssp.cc, iface/gspn/gspn.cc, iface/gspn/gspn.hh,
iface/gspn/ltlgspn.cc, iface/gspn/simple.test, iface/gspn/ssp.cc,
iface/gspn/ssp.hh, iface/gspn/udcsefm.test, iface/gspn/udcseltl.test,
iface/gspn/udcsfm.test, iface/gspn/udcsltl.test, src/Makefile.am,
src/bin/Makefile.am, src/bin/common_cout.cc, src/bin/common_cout.hh,
src/bin/common_finput.cc, src/bin/common_finput.hh,
src/bin/common_output.cc, src/bin/common_output.hh,
src/bin/common_post.cc, src/bin/common_post.hh, src/bin/common_r.cc,
src/bin/common_r.hh, src/bin/common_range.cc, src/bin/common_range.hh,
src/bin/common_setup.cc, src/bin/common_setup.hh,
src/bin/common_sys.hh, src/bin/genltl.cc, src/bin/ltl2tgba.cc,
src/bin/ltl2tgta.cc, src/bin/ltlfilt.cc, src/bin/man/Makefile.am,
src/bin/randltl.cc, src/eltlparse/Makefile.am,
src/eltlparse/eltlparse.yy, src/eltlparse/eltlscan.ll,
src/eltlparse/fmterror.cc, src/eltlparse/parsedecl.hh,
src/eltlparse/public.hh, src/eltltest/Makefile.am,
src/eltltest/acc.cc, src/eltltest/acc.test, src/eltltest/defs.in,
src/eltltest/nfa.cc, src/eltltest/nfa.test, src/evtgba/Makefile.am,
src/evtgba/evtgba.cc, src/evtgba/evtgba.hh, src/evtgba/evtgbaiter.hh,
src/evtgba/explicit.cc, src/evtgba/explicit.hh, src/evtgba/product.cc,
src/evtgba/product.hh, src/evtgba/symbol.cc, src/evtgba/symbol.hh,
src/evtgbaalgos/Makefile.am, src/evtgbaalgos/dotty.cc,
src/evtgbaalgos/dotty.hh, src/evtgbaalgos/reachiter.cc,
src/evtgbaalgos/reachiter.hh, src/evtgbaalgos/save.cc,
src/evtgbaalgos/save.hh, src/evtgbaalgos/tgba2evtgba.cc,
src/evtgbaalgos/tgba2evtgba.hh, src/evtgbaparse/Makefile.am,
src/evtgbaparse/evtgbaparse.yy, src/evtgbaparse/evtgbascan.ll,
src/evtgbaparse/fmterror.cc, src/evtgbaparse/parsedecl.hh,
src/evtgbaparse/public.hh, src/evtgbatest/Makefile.am,
src/evtgbatest/defs.in, src/evtgbatest/explicit.cc,
src/evtgbatest/explicit.test, src/evtgbatest/ltl2evtgba.cc,
src/evtgbatest/ltl2evtgba.test, src/evtgbatest/product.cc,
src/evtgbatest/product.test, src/evtgbatest/readsave.cc,
src/evtgbatest/readsave.test, src/kripke/Makefile.am,
src/kripke/fairkripke.cc, src/kripke/fairkripke.hh,
src/kripke/kripke.cc, src/kripke/kripke.hh,
src/kripke/kripkeexplicit.cc, src/kripke/kripkeexplicit.hh,
src/kripke/kripkeprint.cc, src/kripke/kripkeprint.hh,
src/kripkeparse/Makefile.am, src/kripkeparse/fmterror.cc,
src/kripkeparse/kripkeparse.yy, src/kripkeparse/kripkescan.ll,
src/kripkeparse/parsedecl.hh, src/kripkeparse/public.hh,
src/kripkeparse/scankripke.ll, src/kripketest/Makefile.am,
src/kripketest/bad_parsing.test, src/kripketest/defs.in,
src/kripketest/kripke.test, src/kripketest/parse_print_test.cc,
src/ltlast/Makefile.am, src/ltlast/allnodes.hh,
src/ltlast/atomic_prop.cc, src/ltlast/atomic_prop.hh,
src/ltlast/automatop.cc, src/ltlast/automatop.hh, src/ltlast/binop.cc,
src/ltlast/binop.hh, src/ltlast/bunop.cc, src/ltlast/bunop.hh,
src/ltlast/constant.cc, src/ltlast/constant.hh, src/ltlast/formula.cc,
src/ltlast/formula.hh, src/ltlast/formula_tree.cc,
src/ltlast/formula_tree.hh, src/ltlast/multop.cc,
src/ltlast/multop.hh, src/ltlast/nfa.cc, src/ltlast/nfa.hh,
src/ltlast/predecl.hh, src/ltlast/refformula.cc,
src/ltlast/refformula.hh, src/ltlast/unop.cc, src/ltlast/unop.hh,
src/ltlast/visitor.hh, src/ltlenv/Makefile.am, src/ltlenv/declenv.cc,
src/ltlenv/declenv.hh, src/ltlenv/defaultenv.cc,
src/ltlenv/defaultenv.hh, src/ltlenv/environment.hh,
src/ltlparse/Makefile.am, src/ltlparse/fmterror.cc,
src/ltlparse/ltlfile.cc, src/ltlparse/ltlfile.hh,
src/ltlparse/ltlparse.yy, src/ltlparse/ltlscan.ll,
src/ltlparse/parsedecl.hh, src/ltlparse/public.hh,
src/ltltest/Makefile.am, src/ltltest/consterm.cc,
src/ltltest/consterm.test, src/ltltest/defs.in, src/ltltest/equals.cc,
src/ltltest/equals.test, src/ltltest/kind.cc, src/ltltest/kind.test,
src/ltltest/length.cc, src/ltltest/length.test,
src/ltltest/lunabbrev.test, src/ltltest/nenoform.test,
src/ltltest/parse.test, src/ltltest/parseerr.test,
src/ltltest/readltl.cc, src/ltltest/reduc.cc, src/ltltest/reduc.test,
src/ltltest/reduccmp.test, src/ltltest/reducpsl.test,
src/ltltest/syntimpl.cc, src/ltltest/syntimpl.test,
src/ltltest/tostring.cc, src/ltltest/tostring.test,
src/ltltest/tunabbrev.test, src/ltltest/tunenoform.test,
src/ltltest/utf8.test, src/ltltest/uwrm.test,
src/ltlvisit/Makefile.am, src/ltlvisit/apcollect.cc,
src/ltlvisit/apcollect.hh, src/ltlvisit/clone.cc,
src/ltlvisit/clone.hh, src/ltlvisit/contain.cc,
src/ltlvisit/contain.hh, src/ltlvisit/destroy.cc,
src/ltlvisit/destroy.hh, src/ltlvisit/dotty.cc, src/ltlvisit/dotty.hh,
src/ltlvisit/dump.cc, src/ltlvisit/dump.hh, src/ltlvisit/lbt.cc,
src/ltlvisit/lbt.hh, src/ltlvisit/length.cc, src/ltlvisit/length.hh,
src/ltlvisit/lunabbrev.cc, src/ltlvisit/lunabbrev.hh,
src/ltlvisit/mark.cc, src/ltlvisit/mark.hh, src/ltlvisit/nenoform.cc,
src/ltlvisit/nenoform.hh, src/ltlvisit/postfix.cc,
src/ltlvisit/postfix.hh, src/ltlvisit/randomltl.cc,
src/ltlvisit/randomltl.hh, src/ltlvisit/reduce.cc,
src/ltlvisit/reduce.hh, src/ltlvisit/relabel.cc,
src/ltlvisit/relabel.hh, src/ltlvisit/simpfg.cc,
src/ltlvisit/simpfg.hh, src/ltlvisit/simplify.cc,
src/ltlvisit/simplify.hh, src/ltlvisit/snf.cc, src/ltlvisit/snf.hh,
src/ltlvisit/tostring.cc, src/ltlvisit/tostring.hh,
src/ltlvisit/tunabbrev.cc, src/ltlvisit/tunabbrev.hh,
src/ltlvisit/wmunabbrev.cc, src/ltlvisit/wmunabbrev.hh,
src/misc/Makefile.am, src/misc/acccompl.cc, src/misc/acccompl.hh,
src/misc/accconv.cc, src/misc/accconv.hh, src/misc/bareword.cc,
src/misc/bareword.hh, src/misc/bddalloc.cc, src/misc/bddalloc.hh,
src/misc/bddlt.hh, src/misc/bddop.cc, src/misc/bddop.hh,
src/misc/casts.hh, src/misc/escape.cc, src/misc/escape.hh,
src/misc/fixpool.hh, src/misc/freelist.cc, src/misc/freelist.hh,
src/misc/hash.hh, src/misc/hashfunc.hh, src/misc/intvcmp2.cc,
src/misc/intvcmp2.hh, src/misc/intvcomp.cc, src/misc/intvcomp.hh,
src/misc/ltstr.hh, src/misc/memusage.cc, src/misc/memusage.hh,
src/misc/minato.cc, src/misc/minato.hh, src/misc/modgray.cc,
src/misc/modgray.hh, src/misc/mspool.hh, src/misc/optionmap.cc,
src/misc/optionmap.hh, src/misc/random.cc, src/misc/random.hh,
src/misc/timer.cc, src/misc/timer.hh, src/misc/unique_ptr.hh,
src/misc/version.cc, src/misc/version.hh, src/neverparse/Makefile.am,
src/neverparse/fmterror.cc, src/neverparse/neverclaimparse.yy,
src/neverparse/neverclaimscan.ll, src/neverparse/parsedecl.hh,
src/neverparse/public.hh, src/saba/Makefile.am,
src/saba/explicitstateconjunction.cc,
src/saba/explicitstateconjunction.hh, src/saba/saba.cc,
src/saba/saba.hh, src/saba/sabacomplementtgba.cc,
src/saba/sabacomplementtgba.hh, src/saba/sabastate.hh,
src/saba/sabasucciter.hh, src/sabaalgos/Makefile.am,
src/sabaalgos/sabadotty.cc, src/sabaalgos/sabadotty.hh,
src/sabaalgos/sabareachiter.cc, src/sabaalgos/sabareachiter.hh,
src/sabatest/Makefile.am, src/sabatest/defs.in,
src/sabatest/sabacomplementtgba.cc, src/sanity/Makefile.am,
src/sanity/readme.test, src/sanity/style.test, src/ta/Makefile.am,
src/ta/ta.cc, src/ta/ta.hh, src/ta/taexplicit.cc,
src/ta/taexplicit.hh, src/ta/taproduct.cc, src/ta/taproduct.hh,
src/ta/tgta.cc, src/ta/tgta.hh, src/ta/tgtaexplicit.cc,
src/ta/tgtaexplicit.hh, src/ta/tgtaproduct.cc, src/ta/tgtaproduct.hh,
src/taalgos/Makefile.am, src/taalgos/dotty.cc, src/taalgos/dotty.hh,
src/taalgos/emptinessta.cc, src/taalgos/emptinessta.hh,
src/taalgos/minimize.cc, src/taalgos/minimize.hh,
src/taalgos/reachiter.cc, src/taalgos/reachiter.hh,
src/taalgos/statessetbuilder.cc, src/taalgos/statessetbuilder.hh,
src/taalgos/stats.cc, src/taalgos/stats.hh, src/taalgos/tgba2ta.cc,
src/taalgos/tgba2ta.hh, src/tgba/Makefile.am, src/tgba/bdddict.cc,
src/tgba/bdddict.hh, src/tgba/bddprint.cc, src/tgba/bddprint.hh,
src/tgba/formula2bdd.cc, src/tgba/formula2bdd.hh,
src/tgba/futurecondcol.cc, src/tgba/futurecondcol.hh,
src/tgba/public.hh, src/tgba/sba.hh, src/tgba/state.hh,
src/tgba/statebdd.cc, src/tgba/statebdd.hh, src/tgba/succiter.hh,
src/tgba/succiterconcrete.cc, src/tgba/succiterconcrete.hh,
src/tgba/taatgba.cc, src/tgba/taatgba.hh, src/tgba/tgba.cc,
src/tgba/tgba.hh, src/tgba/tgbabddconcrete.cc,
src/tgba/tgbabddconcrete.hh, src/tgba/tgbabddconcretefactory.cc,
src/tgba/tgbabddconcretefactory.hh,
src/tgba/tgbabddconcreteproduct.cc,
src/tgba/tgbabddconcreteproduct.hh, src/tgba/tgbabddcoredata.cc,
src/tgba/tgbabddcoredata.hh, src/tgba/tgbabddfactory.hh,
src/tgba/tgbaexplicit.cc, src/tgba/tgbaexplicit.hh,
src/tgba/tgbakvcomplement.cc, src/tgba/tgbakvcomplement.hh,
src/tgba/tgbaproduct.cc, src/tgba/tgbaproduct.hh,
src/tgba/tgbasafracomplement.cc, src/tgba/tgbasafracomplement.hh,
src/tgba/tgbascc.cc, src/tgba/tgbascc.hh, src/tgba/tgbasgba.cc,
src/tgba/tgbasgba.hh, src/tgba/tgbatba.cc, src/tgba/tgbatba.hh,
src/tgba/tgbaunion.cc, src/tgba/tgbaunion.hh, src/tgba/wdbacomp.cc,
src/tgba/wdbacomp.hh, src/tgbaalgos/Makefile.am,
src/tgbaalgos/bfssteps.cc, src/tgbaalgos/bfssteps.hh,
src/tgbaalgos/cutscc.cc, src/tgbaalgos/cutscc.hh,
src/tgbaalgos/cycles.cc, src/tgbaalgos/cycles.hh,
src/tgbaalgos/degen.cc, src/tgbaalgos/degen.hh,
src/tgbaalgos/dotty.cc, src/tgbaalgos/dotty.hh,
src/tgbaalgos/dottydec.cc, src/tgbaalgos/dottydec.hh,
src/tgbaalgos/dupexp.cc, src/tgbaalgos/dupexp.hh,
src/tgbaalgos/eltl2tgba_lacim.cc, src/tgbaalgos/eltl2tgba_lacim.hh,
src/tgbaalgos/emptiness.cc, src/tgbaalgos/emptiness.hh,
src/tgbaalgos/emptiness_stats.hh, src/tgbaalgos/gtec/Makefile.am,
src/tgbaalgos/gtec/ce.cc, src/tgbaalgos/gtec/ce.hh,
src/tgbaalgos/gtec/explscc.cc, src/tgbaalgos/gtec/explscc.hh,
src/tgbaalgos/gtec/gtec.cc, src/tgbaalgos/gtec/gtec.hh,
src/tgbaalgos/gtec/nsheap.cc, src/tgbaalgos/gtec/nsheap.hh,
src/tgbaalgos/gtec/sccstack.cc, src/tgbaalgos/gtec/sccstack.hh,
src/tgbaalgos/gtec/status.cc, src/tgbaalgos/gtec/status.hh,
src/tgbaalgos/gv04.cc, src/tgbaalgos/gv04.hh, src/tgbaalgos/isdet.cc,
src/tgbaalgos/isdet.hh, src/tgbaalgos/isweakscc.cc,
src/tgbaalgos/isweakscc.hh, src/tgbaalgos/lbtt.cc,
src/tgbaalgos/lbtt.hh, src/tgbaalgos/ltl2taa.cc,
src/tgbaalgos/ltl2taa.hh, src/tgbaalgos/ltl2tgba_fm.cc,
src/tgbaalgos/ltl2tgba_fm.hh, src/tgbaalgos/ltl2tgba_lacim.cc,
src/tgbaalgos/ltl2tgba_lacim.hh, src/tgbaalgos/magic.cc,
src/tgbaalgos/magic.hh, src/tgbaalgos/minimize.cc,
src/tgbaalgos/minimize.hh, src/tgbaalgos/ndfs_result.hxx,
src/tgbaalgos/neverclaim.cc, src/tgbaalgos/neverclaim.hh,
src/tgbaalgos/postproc.cc, src/tgbaalgos/postproc.hh,
src/tgbaalgos/powerset.cc, src/tgbaalgos/powerset.hh,
src/tgbaalgos/projrun.cc, src/tgbaalgos/projrun.hh,
src/tgbaalgos/randomgraph.cc, src/tgbaalgos/randomgraph.hh,
src/tgbaalgos/reachiter.cc, src/tgbaalgos/reachiter.hh,
src/tgbaalgos/reducerun.cc, src/tgbaalgos/reducerun.hh,
src/tgbaalgos/reductgba_sim.cc, src/tgbaalgos/reductgba_sim.hh,
src/tgbaalgos/replayrun.cc, src/tgbaalgos/replayrun.hh,
src/tgbaalgos/rundotdec.cc, src/tgbaalgos/rundotdec.hh,
src/tgbaalgos/safety.cc, src/tgbaalgos/safety.hh,
src/tgbaalgos/save.cc, src/tgbaalgos/save.hh, src/tgbaalgos/scc.cc,
src/tgbaalgos/scc.hh, src/tgbaalgos/sccfilter.cc,
src/tgbaalgos/sccfilter.hh, src/tgbaalgos/se05.cc,
src/tgbaalgos/se05.hh, src/tgbaalgos/simulation.cc,
src/tgbaalgos/simulation.hh, src/tgbaalgos/stats.cc,
src/tgbaalgos/stats.hh, src/tgbaalgos/tau03.cc,
src/tgbaalgos/tau03.hh, src/tgbaalgos/tau03opt.cc,
src/tgbaalgos/tau03opt.hh, src/tgbaalgos/weight.cc,
src/tgbaalgos/weight.hh, src/tgbaparse/Makefile.am,
src/tgbaparse/fmterror.cc, src/tgbaparse/parsedecl.hh,
src/tgbaparse/public.hh, src/tgbaparse/tgbaparse.yy,
src/tgbaparse/tgbascan.ll, src/tgbatest/Makefile.am,
src/tgbatest/babiak.test, src/tgbatest/bddprod.test,
src/tgbatest/complementation.cc, src/tgbatest/complementation.test,
src/tgbatest/cycles.test, src/tgbatest/defs.in,
src/tgbatest/degendet.test, src/tgbatest/degenid.test,
src/tgbatest/dfs.test, src/tgbatest/dupexp.test,
src/tgbatest/eltl2tgba.test, src/tgbatest/emptchk.test,
src/tgbatest/emptchke.test, src/tgbatest/emptchkr.test,
src/tgbatest/explicit.cc, src/tgbatest/explicit.test,
src/tgbatest/explicit2.cc, src/tgbatest/explicit2.test,
src/tgbatest/explpro2.test, src/tgbatest/explpro3.test,
src/tgbatest/explpro4.test, src/tgbatest/explprod.cc,
src/tgbatest/explprod.test, src/tgbatest/intvcmp2.cc,
src/tgbatest/intvcomp.cc, src/tgbatest/intvcomp.test,
src/tgbatest/kv.test, src/tgbatest/ltl2neverclaim.test,
src/tgbatest/ltl2ta.test, src/tgbatest/ltl2tgba.cc,
src/tgbatest/ltl2tgba.test, src/tgbatest/ltlcounter.test,
src/tgbatest/ltlprod.cc, src/tgbatest/ltlprod.test,
src/tgbatest/mixprod.cc, src/tgbatest/mixprod.test,
src/tgbatest/neverclaimread.test, src/tgbatest/nondet.test,
src/tgbatest/obligation.test, src/tgbatest/powerset.cc,
src/tgbatest/randpsl.test, src/tgbatest/randtgba.cc,
src/tgbatest/randtgba.test, src/tgbatest/readsave.test,
src/tgbatest/renault.test, src/tgbatest/scc.test,
src/tgbatest/sccsimpl.test, src/tgbatest/spotlbtt.test,
src/tgbatest/spotlbtt2.test, src/tgbatest/taatgba.cc,
src/tgbatest/taatgba.test, src/tgbatest/tgbaread.cc,
src/tgbatest/tgbaread.test, src/tgbatest/tripprod.cc,
src/tgbatest/tripprod.test, src/tgbatest/wdba.test,
src/tgbatest/wdba2.test, wrap/Makefile.am, wrap/python/Makefile.am,
wrap/python/ajax/Makefile.am, wrap/python/ajax/spot.in,
wrap/python/buddy.i, wrap/python/spot.i,
wrap/python/tests/Makefile.am, wrap/python/tests/alarm.py,
wrap/python/tests/bddnqueen.py, wrap/python/tests/implies.py,
wrap/python/tests/interdep.py, wrap/python/tests/ltl2tgba.py,
wrap/python/tests/ltl2tgba.test, wrap/python/tests/ltlparse.py,
wrap/python/tests/ltlsimple.py, wrap/python/tests/minato.py,
wrap/python/tests/modgray.py, wrap/python/tests/optionmap.py,
wrap/python/tests/parsetgba.py, wrap/python/tests/run.in,
wrap/python/tests/setxor.py: Update licence version, and replace the
FSF address by a URL.
2012-10-12 22:05:18 +02:00

779 lines
16 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// -*- coding: utf-8 -*-
// Copyright (C) 2008, 2010, 2012 Laboratoire de Recherche et
// Développement de l'Epita (LRDE)
// Copyright (C) 2003, 2004 Laboratoire d'Informatique de Paris 6 (LIP6),
// département Systèmes Répartis Coopératifs (SRC), Université Pierre
// et Marie Curie.
//
// 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/>.
#include <cassert>
#include <sstream>
#include <ctype.h>
#include <ostream>
#include <cstring>
#include "ltlast/allnodes.hh"
#include "ltlast/visitor.hh"
#include "lunabbrev.hh"
#include "wmunabbrev.hh"
#include "tostring.hh"
namespace spot
{
namespace ltl
{
namespace
{
enum keyword {
KFalse = 0,
KTrue = 1,
KEmptyWord = 2,
KXor,
KImplies,
KEquiv,
KU,
KR,
KW,
KM,
KEConcat,
KEConcatNext,
KEConcatMarked,
KEConcatMarkedNext,
KUConcat,
KUConcatNext,
KNot,
KX,
KF,
KG,
KOr,
KOrRat,
KAnd,
KAndRat,
KAndNLM,
KConcat,
KFusion,
};
const char* spot_kw[] = {
"0",
"1",
"[*0]",
" xor ",
" -> ",
" <-> ",
" U ",
" R ",
" W ",
" M ",
"<>-> ",
"<>=> ",
"<>+> ",
"<>=+> ",
"[]-> ",
"[]=> ",
"!",
"X",
"F",
"G",
" | ",
" | ",
" & ",
" && ",
" & ",
";",
":",
};
const char* spin_kw[] = {
"0",
"1",
"[*0]", // not supported
" xor ", // rewritten
" -> ", // rewritten, although supported
" <-> ", // rewritten, although supported
" U ",
" V ",
" W ", // rewritten, although supported
" M ", // rewritten
"<>-> ", // not supported
"<>=> ", // not supported
"<>+> ", // not supported
"<>=+> ", // not supported
"[]-> ", // not supported
"[]=> ", // not supported
"!",
"X",
"<>",
"[]",
" || ",
" || ",
" && ",
" && ", // not supported
" & ", // not supported
";", // not supported
":", // not supported
};
const char* utf8_kw[] = {
"0",
"1",
"[*0]",
"",
"",
"",
" U ",
" R ",
" W ",
" M ",
"◇→ ",
"◇⇒ ",
"◇→̃ ",
"◇⇒̃ ",
"□→ ",
"□⇒ ",
"¬",
"",
"",
"",
"",
" | ",
"",
"",
" & ",
";",
":",
};
static bool
is_bare_word(const char* str)
{
// Bare words cannot be empty, start with the letter of a unary
// operator, or be the name of an existing constant. Also they
// should start with an letter.
if (!*str
|| *str == 'F'
|| *str == 'G'
|| *str == 'X'
|| !(isalpha(*str) || *str == '_')
|| !strcasecmp(str, "true")
|| !strcasecmp(str, "false"))
return false;
// The remaining of the word must be alphanumeric.
while (*++str)
if (!(isalnum(*str) || *str == '_'))
return false;
return true;
}
// If the formula has the form (!b)[*], return b.
static
const formula*
strip_star_not(const formula* f)
{
if (const bunop* s = is_Star(f))
if (const unop* n = is_Not(s->child()))
return n->child();
return 0;
}
// If the formula as position i in multop mo has the form
// (!b)[*];b with b being a Boolean formula, return b.
static
const formula*
match_goto(const multop *mo, unsigned i)
{
assert(i + 1 < mo->size());
const formula* b = strip_star_not(mo->nth(i));
if (!b || !b->is_boolean())
return 0;
if (mo->nth(i + 1) == b)
return b;
return 0;
}
class to_string_visitor: public visitor
{
public:
to_string_visitor(std::ostream& os,
bool full_parent = false,
bool ratexp = false,
const char** kw = spot_kw)
: os_(os), top_level_(true),
full_parent_(full_parent), in_ratexp_(ratexp),
kw_(kw)
{
}
virtual
~to_string_visitor()
{
}
void
openp() const
{
os_ << (in_ratexp_ ? "{" : "(");
}
void
closep() const
{
os_ << (in_ratexp_ ? "}" : ")");
}
std::ostream&
emit(int symbol)
{
return os_ << kw_[symbol];
}
void
visit(const atomic_prop* ap)
{
std::string str = ap->name();
if (full_parent_)
os_ << "(";
if (!is_bare_word(str.c_str()))
{
os_ << '"' << str << '"';
}
else
{
os_ << str;
}
if (full_parent_)
os_ << ")";
}
void
visit(const constant* c)
{
if (full_parent_)
openp();
switch (c->val())
{
case constant::False:
emit(KFalse);
break;
case constant::True:
emit(KTrue);
break;
case constant::EmptyWord:
emit(KEmptyWord);
break;
}
if (full_parent_)
closep();
}
void
visit(const binop* bo)
{
bool top_level = top_level_;
top_level_ = false;
if (!top_level)
openp();
bool onelast = false;
switch (bo->op())
{
case binop::UConcat:
case binop::EConcat:
case binop::EConcatMarked:
os_ << "{";
in_ratexp_ = true;
top_level_ = true;
{
const multop* m = is_multop(bo->first(), multop::Concat);
if (m)
{
unsigned s = m->size();
if (m->nth(s - 1) == constant::true_instance())
{
const formula* tmp = m->all_but(s - 1);
tmp->accept(*this);
tmp->destroy();
onelast = true;
break;
}
}
}
// fall through
default:
bo->first()->accept(*this);
break;
}
switch (bo->op())
{
case binop::Xor:
emit(KXor);
break;
case binop::Implies:
emit(KImplies);
break;
case binop::Equiv:
emit(KEquiv);
break;
case binop::U:
emit(KU);
break;
case binop::R:
emit(KR);
break;
case binop::W:
emit(KW);
break;
case binop::M:
emit(KM);
break;
case binop::UConcat:
os_ << "}";
emit(onelast ? KUConcatNext : KUConcat);
in_ratexp_ = false;
top_level_ = top_level;
break;
case binop::EConcat:
if (bo->second() == constant::true_instance())
{
os_ << "}!";
in_ratexp_ = false;
goto second_done;
}
os_ << "}";
emit(onelast ? KEConcatNext : KEConcat);
in_ratexp_ = false;
top_level_ = false;
break;
case binop::EConcatMarked:
os_ << "}";
emit(onelast ? KEConcatMarkedNext : KEConcatMarked);
in_ratexp_ = false;
top_level_ = false;
break;
}
bo->second()->accept(*this);
second_done:
if (!top_level)
closep();
}
void
emit_bunop_child(const formula* b)
{
// b[*] is OK, no need to print {b}[*]. However want braces
// for {!b}[*], the only unary operator that can be nested
// with [*] or any other BUnOp like [->i..j] or [=i..j].
formula::opkind ck = b->kind();
bool need_parent = (full_parent_
|| ck == formula::UnOp
|| ck == formula::BinOp
|| ck == formula::MultOp);
if (need_parent)
openp();
b->accept(*this);
if (need_parent)
closep();
}
void
visit(const bunop* bo)
{
const formula* c = bo->child();
enum { Star, Goto, Equal } sugar = Star;
unsigned default_min = 0;
unsigned default_max = bunop::unbounded;
// Abbreviate "1[*]" as "[*]".
if (c != constant::true_instance())
{
bunop::type op = bo->op();
switch (op)
{
case bunop::Star:
if (const multop* mo = is_Concat(c))
{
unsigned s = mo->size();
if (s == 2)
if (const formula* b = match_goto(mo, 0))
{
c = b;
sugar = Goto;
}
}
break;
}
emit_bunop_child(c);
}
unsigned min = bo->min();
unsigned max = bo->max();
switch (sugar)
{
case Star:
if (min == 1 && max == bunop::unbounded)
{
os_ << "[+]";
return;
}
os_ << "[*";
break;
case Equal:
os_ << "[=";
break;
case Goto:
os_ << "[->";
default_min = 1;
default_max = 1;
break;
}
// Beware that the default parameters of the Goto operator are
// not the same as Star or Equal:
//
// [->] = [->1..1]
// [->..] = [->1..unbounded]
// [*] = [*0..unbounded]
// [*..] = [*0..unbounded]
// [=] = [=0..unbounded]
// [=..] = [=0..unbounded]
//
// Strictly speaking [=] is not specified by PSL, and anyway we
// automatically rewrite Exp[=0..unbounded] as
// Exp[*0..unbounded], so we should never have to print [=]
// here.
//
// Also
// [*..] = [*0..unbounded]
if (min != default_min || max != default_max)
{
// Always print the min_, even when it is equal to
// default_min, this way we avoid ambiguities (like
// when reading [*..3] near [->..2])
os_ << min;
if (min != max)
{
os_ << "..";
if (max != bunop::unbounded)
os_ << max;
}
}
os_ << "]";
}
void
visit(const unop* uo)
{
top_level_ = false;
// The parser treats F0, F1, G0, G1, X0, and X1 as atomic
// propositions. So make sure we output F(0), G(1), etc.
bool need_parent = (uo->child()->kind() == formula::Constant);
bool top_level = top_level_;
bool overline = false;
if (full_parent_)
{
need_parent = false; // These will be printed by each subformula
if (!top_level)
openp();
}
switch (uo->op())
{
case unop::Not:
need_parent = false;
// If we negate a single letter in UTF-8, use a
// combining overline.
if (!full_parent_ && kw_ == utf8_kw)
if (const ltl::atomic_prop* ap = is_atomic_prop(uo->child()))
if (ap->name().size() == 1
&& is_bare_word(ap->name().c_str()))
{
overline = true;
break;
}
emit(KNot);
break;
case unop::X:
emit(KX);
break;
case unop::F:
emit(KF);
break;
case unop::G:
emit(KG);
break;
case unop::Finish:
os_ << "finish";
need_parent = true;
break;
case unop::Closure:
os_ << "{";
in_ratexp_ = true;
top_level_ = true;
break;
case unop::NegClosure:
emit(KNot);
os_ << "{";
in_ratexp_ = true;
top_level_ = true;
break;
case unop::NegClosureMarked:
emit(KNot);
os_ << (kw_ == utf8_kw ? "̃{": "+{");
in_ratexp_ = true;
top_level_ = true;
break;
}
if (need_parent || full_parent_)
openp();
uo->child()->accept(*this);
if (need_parent || full_parent_)
closep();
switch (uo->op())
{
case unop::Closure:
case unop::NegClosure:
os_ << "}";
in_ratexp_ = false;
top_level_ = false;
break;
default:
break;
}
if (full_parent_ && !top_level)
closep();
else if (overline)
// The following string contains only the character U+0305
// (a combining overline). It looks better than U+0304 (a
// combining overbar).
os_ << "̅";
}
void
visit(const automatop* ao)
{
// Warning: this string isn't parsable because the automaton
// operators used may not be defined.
bool top_level = top_level_;
top_level_ = false;
if (!top_level)
os_ << "(";
os_ << ao->get_nfa()->get_name() << "(";
unsigned max = ao->size();
ao->nth(0)->accept(*this);
for (unsigned n = 1; n < max; ++n)
{
os_ << ",";
ao->nth(n)->accept(*this);
}
os_ << ")";
if (!top_level)
os_ << ")";
}
void
resugar_concat(const multop* mo)
{
unsigned max = mo->size();
for (unsigned i = 0; i < max; ++i)
{
if (i > 0)
emit(KConcat);
if (i + 1 < max)
{
// Try to match (!b)[*];b
const formula* b = match_goto(mo, i);
if (b)
{
emit_bunop_child(b);
// Wait... maybe we are looking at (!b)[*];b;(!b)[*]
// in which case it's b[=1].
if (i + 2 < max && mo->nth(i) == mo->nth(i + 2))
{
os_ << "[=1]";
i += 2;
}
else
{
os_ << "[->]";
++i;
}
continue;
}
// Try to match ((!b)[*];b)[*i..j];(!b)[*]
if (const bunop* s = is_Star(mo->nth(i)))
if (const formula* b2 = strip_star_not(mo->nth(i + 1)))
if (const multop* sc = is_Concat(s->child()))
if (const formula* b1 = match_goto(sc, 0))
if (b1 == b2)
{
emit_bunop_child(b1);
os_ << "[=";
unsigned min = s->min();
os_ << min;
unsigned max = s->max();
if (max != min)
{
os_ << "..";
if (max != bunop::unbounded)
os_ << max;
}
os_ << "]";
++i;
continue;
}
}
mo->nth(i)->accept(*this);
}
}
void
visit(const multop* mo)
{
bool top_level = top_level_;
top_level_ = false;
if (!top_level)
openp();
multop::type op = mo->op();
// Handle the concatenation separately, because we want to
// "resugar" some patterns.
if (op == multop::Concat)
{
resugar_concat(mo);
if (!top_level)
closep();
return;
}
mo->nth(0)->accept(*this);
keyword k = KFalse; // Initialize to something to please GCC.
switch (op)
{
case multop::Or:
k = KOr;
break;
case multop::OrRat:
k = KOrRat;
break;
case multop::And:
k = in_ratexp_ ? KAndRat : KAnd;
break;
case multop::AndRat:
k = KAndRat;
break;
case multop::AndNLM:
k = KAndNLM;
break;
case multop::Concat:
// Handled by resugar_concat.
assert(0);
break;
case multop::Fusion:
k = KFusion;
break;
}
assert(k != KFalse);
unsigned max = mo->size();
for (unsigned n = 1; n < max; ++n)
{
emit(k);
mo->nth(n)->accept(*this);
}
if (!top_level)
closep();
}
protected:
std::ostream& os_;
bool top_level_;
bool full_parent_;
bool in_ratexp_;
const char** kw_;
};
} // anonymous
std::ostream&
to_string(const formula* f, std::ostream& os, bool full_parent,
bool ratexp)
{
to_string_visitor v(os, full_parent, ratexp, spot_kw);
f->accept(v);
return os;
}
std::string
to_string(const formula* f, bool full_parent, bool ratexp)
{
std::ostringstream os;
to_string(f, os, full_parent, ratexp);
return os.str();
}
std::ostream&
to_utf8_string(const formula* f, std::ostream& os, bool full_parent,
bool ratexp)
{
to_string_visitor v(os, full_parent, ratexp, utf8_kw);
f->accept(v);
return os;
}
std::string
to_utf8_string(const formula* f, bool full_parent, bool ratexp)
{
std::ostringstream os;
to_utf8_string(f, os, full_parent, ratexp);
return os.str();
}
std::ostream&
to_spin_string(const formula* f, std::ostream& os, bool full_parent)
{
// Remove xor, ->, and <-> first.
const formula* fu = unabbreviate_logic(f);
// Also remove W and M.
f = unabbreviate_wm(fu);
fu->destroy();
to_string_visitor v(os, full_parent, false, spin_kw);
f->accept(v);
f->destroy();
return os;
}
std::string
to_spin_string(const formula* f, bool full_parent)
{
std::ostringstream os;
to_spin_string(f, os, full_parent);
return os.str();
}
}
}