package schema import ( "logik/aussagenlogik/formulae" parser "logik/grammars/aussagenlogik" "github.com/antlr/antlr4/runtime/Go/antlr" ) /* ---------------------------------------------------------------- * * EXPORTS * ---------------------------------------------------------------- */ func ParseExpr(u string) formulae.Formula { var lexer = createLexer(u) var tokenStream = lexerToTokenStream(lexer) var prs = parser.NewaussagenlogikParser(tokenStream) var t = prs.Start() tree := createFormula(t, prs) return tree } /* ---------------------------------------------------------------- * * PRIVATE * ---------------------------------------------------------------- */ func exprToStream(u string) *antlr.InputStream { return antlr.NewInputStream(u) } func lexerToTokenStream(lexer antlr.Lexer) antlr.TokenStream { return antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel) } func createLexer(u string) antlr.Lexer { stream := exprToStream(u) return parser.NewaussagenlogikLexer(stream) } func createFormula(tree antlr.Tree, parser antlr.Parser) formulae.Formula { var ant = antlrTree{tree: tree, parser: &parser} return ant.toFormula() } /* ---------------------------------------------------------------- * * Struct: antlrTree + Methods * ---------------------------------------------------------------- */ type antlrTree struct { tree antlr.Tree parser *antlr.Parser } func (ant antlrTree) getChildren() []antlrTree { var nodes = ant.tree.GetChildren() var subants = make([]antlrTree, len(nodes)) for i, node := range nodes { subants[i] = antlrTree{tree: node, parser: ant.parser} } return subants } func (ant antlrTree) getLabel() string { return antlr.TreesGetNodeText(ant.tree, []string{}, *ant.parser) } func (ant antlrTree) getTextContent() string { var expr string = ant.getLabel() for _, subant := range ant.getChildren() { expr += subant.getTextContent() } return expr } func (ant antlrTree) getTextContentLeaves() string { var expr string = "" var subants = ant.getChildren() if len(subants) == 0 { expr = ant.getLabel() } else { for _, subant := range subants { expr += subant.getTextContent() } } return expr } func (ant antlrTree) toFormula() formulae.Formula { var label string = ant.getLabel() var subants = ant.getChildren() var nChildren = len(subants) switch label { case "start": if nChildren == 1 { return subants[0].toFormula() } case "open": if nChildren == 1 { return subants[0].toFormula() } case "closed": switch nChildren { case 1: return subants[0].toFormula() // expr = ( expr ) case 3: return subants[1].toFormula() } case "atomic": if nChildren == 1 { return subants[0].toFormula() } case "taut": return formulae.Tautology case "contradiction": return formulae.Contradiction case "atom": return formulae.Atom(ant.getTextContentLeaves()) case "generic": return formulae.Generic(ant.getTextContentLeaves()) case "not": // NOTE: expr = ! expr if nChildren == 2 { return formulae.Negation(subants[1].toFormula()) } case "and2": // NOTE: expr = expr && expr if nChildren == 3 { return formulae.Conjunction2(subants[0].toFormula(), subants[2].toFormula()) } case "or2": // NOTE: expr = expr || expr if nChildren == 3 { return formulae.Disjunction2(subants[0].toFormula(), subants[2].toFormula()) } case "implies": // NOTE: expr = expr -> expr if nChildren == 3 { return formulae.Implies(subants[0].toFormula(), subants[2].toFormula()) } case "iff": // NOTE: expr = expr <=> expr if nChildren == 3 { return formulae.DoubleImplication(subants[0].toFormula(), subants[2].toFormula()) } case "and", "or": // NOTE: expr = expr op expr op ... op expr var n int = int((len(subants) + 1) / 2) if nChildren == 2*n-1 && n >= 2 { var subtrees = make([]formulae.Formula, n) var isSymb bool = true var i int = 0 for _, subant := range subants { if isSymb { subtrees[i] = subant.toFormula() i++ } // NOTE: infix notation: alternatives between expression and symbol isSymb = !isSymb } switch label { case "and": return formulae.Conjunction(subtrees) case "or": return formulae.Disjunction(subtrees) } } } panic("Could not parse expression") }