Skip to content

Parsing

One of the core features of the library is the support of parsing strings compliant to a certain grammar to handily build formulae.

The parsing functions, one for each logic formalism, can be imported from pylogics.parsers, and their name is parse_<id>, where <id> is the identifier of the logic formalism. For example, the parsing for propositional logic (pl) is parse_pl, whereas the parsing function for Linear Temporal Logic (ltl) is parse_ltl. For a list of the supported logics and their identifier please look at this page.

The library uses Lark to generate the parser automatically. The grammar files are reported at this page.

The syntax for LTL, PLTL and LDL aims to be compliant with this specification.

Symbols

A symbol is determined by the following regular expression:

SYMBOL: [a-z][a-z0-9_]*|"\w+"

That is:

  • if between quotes "", a symbol can be any non-empty sequence of word characters: [a-zA-Z0-9_]+
  • if not, a symbol must:

    • have only have lower case characters
    • have at least one character and start with a non-digit character.

Propositional Logic

Informally, the supported grammar for propositional logic is:

pl_formula: pl_formula <-> pl_formula  // equivalence
          | pl_formula ->  pl_formula  // implication 
          | pl_formula ||  pl_formula  // disjunction 
          | pl_formula &&  pl_formula  // conjunction 
          | !pl_formula                // negation
          | ( pl_formula )             // brackets 
          | true                       // boolean propositional constant
          | false                      // boolean propositional constant
          | SYMBOL                     // prop. atom

Some examples:

from pylogics.parsers import parse_pl
parse_pl("a")
parse_pl("b")
parse_pl("a & b")
parse_pl("a | b")
parse_pl("a >> b")
parse_pl("a <-> b")
parse_pl("a <-> a")       # returns a
parse_pl("!(a)")
parse_pl("true | false")  # returns true
parse_pl("true & false")  # returns false

Linear Temporal Logic

Informally, the supported grammar for linear temporal logic is:

ltl_formula: ltl_formula <-> ltl_formula  // equivalence
           | ltl_formula ->  ltl_formula  // implication 
           | ltl_formula ||  ltl_formula  // disjunction 
           | ltl_formula &&  ltl_formula  // conjunction 
           | !ltl_formula                 // negation
           | ( ltl_formula )              // brackets
           | ltl_formula U ltl_formula    // until 
           | ltl_formula R ltl_formula    // release 
           | ltl_formula W ltl_formula    // weak until 
           | ltl_formula M ltl_formula    // strong release 
           | F ltl_formula                // eventually 
           | G ltl_formula                // always 
           | X[!] ltl_formula             // next 
           | X ltl_formula                // weak next 
           | true                         // boolean propositional constant
           | false                        // boolean propositional constant
           | tt                           // boolean logical constant
           | ff                           // boolean logical constant
           | SYMBOL                       // propositional atom

Some examples:

from pylogics.parsers import parse_ltl
parse_ltl("tt")
parse_ltl("ff")
parse_ltl("true")
parse_ltl("false")
parse_ltl("a")
parse_ltl("b")
parse_ltl("X(a)")
parse_ltl("X[!](b)")
parse_ltl("F(a)")
parse_ltl("G(b)")
parse_ltl("G(a -> b)")
parse_ltl("a U b")
parse_ltl("a R b")
parse_ltl("a W b")
parse_ltl("a M b")

Past Linear Temporal Logic

Informally, the supported grammar for past linear temporal logic is:

pltl_formula: pltl_formula <-> pltl_formula  // equivalence
            | pltl_formula ->  pltl_formula  // implication 
            | pltl_formula ||  pltl_formula  // disjunction 
            | pltl_formula &&  pltl_formula  // conjunction 
            | !pltl_formula                  // negation
            | ( pltl_formula )               // brackets
            | pltl_formula S pltl_formula    // since 
            | H pltl_formula                 // historically
            | O pltl_formula                 // once 
            | Y pltl_formula                 // before 
            | true                           // boolean propositional constant
            | false                          // boolean propositional constant
            | tt                             // boolean logical constant
            | ff                             // boolean logical constant
            | SYMBOL                         // propositional atom

Some examples:

from pylogics.parsers import parse_pltl
parse_pltl("tt")
parse_pltl("ff")
parse_pltl("true")
parse_pltl("false")
parse_pltl("a")
parse_pltl("b")
parse_pltl("Y(a)")
parse_pltl("O(b)")
parse_pltl("H(a)")
parse_pltl("a S b")

Linear Dynamic Logic

Informally, the supported grammar for linear dynamic logic is (note; it is doubly-inductive):

ldl_formula: ldl_formula <-> ldl_formula   // equivalence
           | ldl_formula ->  ldl_formula   // implication 
           | ldl_formula ||  ldl_formula   // disjunction 
           | ldl_formula &&  ldl_formula   // conjunction 
           | !ldl_formula                  // negation
           | ( ldl_formula )               // brackets
           | <regex>ldl_formula            // diamond formula
           | [regex]ldl_formula            // box formula
           | tt                            // boolean constant
           | ff                            // boolean constant

regex      : regex + regex                 // union 
           | regex ; regex                 // sequence 
           | ?regex                        // test 
           | regex*                        // star 
           | pl_formula                    // prop. formula (see above) 

Note: the question mark in the test regular expression is on the left, not on the right. This is done to avoid parse conflicts in the parser generation.

Some examples:

from pylogics.parsers import parse_ldl
parse_ldl("tt")
parse_ldl("ff")
parse_ldl("<a>tt")
parse_ldl("[a & b]ff")
parse_ldl("<a + b>tt")
parse_ldl("<a ; b><c>tt")
parse_ldl("<(a ; b)*><c>tt")
parse_ldl("<true><a>tt")  # Next a
parse_ldl("<(<a>tt?;true)*>(<b>tt)")  # (a Until b) in LDLf