master > master: Schema robuster gemacht; simple class, um Aspekte leichter aufzurufen

This commit is contained in:
RD
2021-05-06 23:34:25 +02:00
parent 6f6de00296
commit 28a1e313b3
4 changed files with 131 additions and 73 deletions

View File

@@ -11,6 +11,7 @@ from __future__ import annotations;
from lark import Lark;
from lark import Tree;
from typing import List;
from typing import Union;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# GLOBALE KONSTANTEN
@@ -24,42 +25,84 @@ lexerAussagenlogik = Lark(
%import common.WORD
%ignore WS
?start: expr
?start: expr | open
?expr: atomic | expr_not | expr_and | expr_or | expr_implies
?literal: atomic | "not" atomic
?expr: atomic | not | closed
?open: and | and_long | or | or_long | impl
?closed: "(" open ")"
// atomische Ausdrücke
?atomic: false | true | atom | generic
?false: "0" -> wahr
?true: "1" -> falsch
?atom: /A[0-9]+/ -> atom
?generic: "{" /((?!({|})).)+/ "}" -> beliebig
?false: "0" -> kontr
?true: "1" -> taut
?atom: /A[0-9]+/ -> atom
?generic: "{" /((?!({|})).)+/ "}" -> beliebig
// Symbole
?conn_not: "!" -> junktor
?conn_and: /&+/ -> junktor
?conn_or: /\\|+/ -> junktor
?conn_impl: /->|=>/ -> junktor
?symb_not: /!/ -> symb
?symb_and: /&+/ -> symb
?symb_or: /\\|+/ -> symb
?symb_impl: /->|=>/ -> symb
// Junktoren
?expr_not: conn_not expr -> negation
?expr_and: "(" expr conn_and expr ")" -> konjunktion
?expr_or: "(" expr conn_or expr ")" -> disjunktion
?expr_implies: "(" expr conn_impl expr ")" -> implikation
?not: symb_not expr -> neg
?and: expr symb_and expr -> konj
?and_long: [ expr ( symb_and expr )+ ] -> konj_lang
?or: expr symb_or expr -> disj
?or_long: [ expr ( symb_or expr )+ ] -> disj_lang
?impl: expr symb_impl expr -> impl
''',
start="expr",
regex=True
);
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# KLASSE: Syntaxbaum
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class SyntaxBaum(object):
expr: str;
kind: str;
children: List[SyntaxBaum];
tree: Tree;
def __init__(self, fml: Tree):
self.kind = fml.data;
if len(fml.children) == 1 and isinstance(fml.children[0], str):
self.expr = fml.children[0];
self.children = [];
self.tree = Tree(self.kind, fml.children);
else:
self.children = [ SyntaxBaum(child) for child in fml.children if isinstance(child, Tree) and child.data != 'symb' ];
self.tree = Tree(self.kind, [child.tree for child in self.children]);
signature_parts = [];
i = 0;
for teilfml in fml.children:
if isinstance(teilfml, str):
signature_parts.append(teilfml);
elif teilfml.data == 'symb':
signature_parts.append(getText(teilfml));
else:
signature_parts.append('{{{}}}'.format(i));
i += 1;
signature = ' '.join(signature_parts);
self.expr = signature.format(*self.children);
if self.kind in [ 'konj', 'konj_lang', 'disj', 'disj_lang', 'impl' ]:
self.expr = '( {} )'.format(self.expr);
return;
def __str__(self):
return self.expr;
def pretty(self):
return self.tree.pretty();
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHODE: string -> Syntaxbaum
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def stringToSyntaxbaum(u: str) -> Tree:
def stringToSyntaxbaum(u: str) -> SyntaxBaum:
try:
u_lexed = lexerAussagenlogik.parse(u);
return u_lexed;
return SyntaxBaum(lexerAussagenlogik.parse(u));
except:
raise Exception('Ausdruck \033[1m{}\033[0m konnte nicht erkannt werden!'.format(u));
@@ -67,47 +110,52 @@ def stringToSyntaxbaum(u: str) -> Tree:
# METHODEN: Erkennung von Formeltypen
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def isAtom(fml: Tree) -> bool:
return fml.data == 'atom';
def isAtom(fml: SyntaxBaum) -> bool:
return fml.kind == 'atom';
def isBeliebig(fml: Tree) -> bool:
return fml.data == 'beliebig';
def isBeliebig(fml: SyntaxBaum) -> bool:
return fml.kind == 'beliebig';
def isTrueSymbol(fml: Tree) -> bool:
return fml.data == 'wahr';
def isTrueSymbol(fml: SyntaxBaum) -> bool:
return fml.kind == 'taut';
def isFalseSymbol(fml: Tree) -> bool:
return fml.data == 'falsch';
def isFalseSymbol(fml: SyntaxBaum) -> bool:
return fml.kind == 'kontr';
def isNegation(fml: Tree) -> bool:
return fml.data == 'negation';
def isNegation(fml: SyntaxBaum) -> bool:
return fml.kind == 'neg';
def isConjunction(fml: Tree) -> bool:
return fml.data == 'konjunktion';
def isConjunction(fml: SyntaxBaum) -> bool:
return fml.kind == 'konj';
def isDisjunction(fml: Tree) -> bool:
return fml.data == 'disjunktion';
def isLongConjunction(fml: SyntaxBaum) -> bool:
return fml.kind == 'konj_lang';
def isImplication(fml: Tree) -> bool:
return fml.data == 'implikation';
def isDisjunction(fml: SyntaxBaum) -> bool:
return fml.kind == 'disj';
def isLongDisjunction(fml: SyntaxBaum) -> bool:
return fml.kind == 'disj_lang';
def isImplication(fml: SyntaxBaum) -> bool:
return fml.kind == 'impl';
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHODEN: Formel -> Teilformeln
# METHODEN: Formel -> Textinhalt
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def getTeilformeln(fml: Tree) -> List[Tree]:
return [
part for part in fml.children
if isinstance(part, Tree)
and not part.data == 'junktor'
];
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHODEN: Formel (Atom/Beliebig) -> Name
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def getName(fml: Tree) -> str:
def getText(fml: Tree) -> str:
text = fml.children[0];
if isinstance(text, str):
return text;
raise Exception('Konnte Textinhalt nicht ablesen!');
def getName(fml: SyntaxBaum) -> str:
return fml.expr;
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# METHODEN: Formel -> Textinhalt
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
def prettifyTree(fml: Union[Tree, SyntaxBaum]) -> str:
return fml.pretty();