master > master: codego initialisiert

This commit is contained in:
RD 2021-05-09 18:22:12 +02:00
parent f4ee7601fd
commit f1a957db03
17 changed files with 1255 additions and 0 deletions

25
codego/.gitignore vendored Normal file
View File

@ -0,0 +1,25 @@
*
!/.gitignore
!/data.env
!/README.md
!/run.sh
!/test.sh
## Go Source
!/aussagenlogik
!/aussagenlogik/rekursion
!/aussagenlogik/schema
!/aussagenlogik/syntaxbaum
!/core
!/core/environment
!/core/utils
!/grammars
!/**/*.go
!/go.mod
!/go.sum
## Für Erzeugung von Grammatiken:
!/grammars/antlr.jar
!/grammars/README.md
!/grammars/*.g4

64
codego/README.md Normal file
View File

@ -0,0 +1,64 @@
# Code in golang #
Die Inhalte dieses Ordners sind absolut **kein Pflichtbestandteil** des Kurses.
Diese dienen nur zur Demonstration / konkreten Verwirklichung von Verfahren, die im Kurs auftauchen. Für Wissbegierige mit auch grundlegenden Programmierkenntnissen bietet sich dies als Möglichkeit an, um sich selbst zu überzeugen, dass strukturelle Rekursion funktioniert.
Der Gebrauch dieser Skripte unterliegt der Eigenverantwortung von Studierenden.
Da ich kein Informatiker bin, sind auch einige Aspekt bestimmt nicht optimal programmiert/strukturiert.
## Systemvoraussetzungen ##
- bash (auch bash-for-windows).
- golang (mind. 1.6.x)
## Voreinstellungen ##
- In einer bash-console zu diesem Ordner navigieren und folgenden Befehl ausführen:
```bash
chmod +x run.sh test.sh
## oder
chmod +x *.sh
```
- In `run.sh` gibt es eine Zeile, die zur Kompilierung des Go-Projektes notwendigen Module über **go** installieren lässt. (Die Liste der Packages findet man in der Datei `requirements`). Diese Zeile kann man ruhig nach der ersten Ausführung rauskommentieren.
## Daten ##
In `data.env` kann man Daten (aktuell: auszuwertenden Ausdruck + Interpretation/Modell) eintragen. Man beachte dabei die Syntax.
## Gebrauchshinweise ##
In einer bash-console zu diesem Ordner navigieren und
```bash
./run.sh
## oder
go build main.go && ./main
```
ausführen.
## Offene Challenges ##
In der Datei `aussagenlogik/rekursion.go` (relativ zu diesem Ordner) findet man mehrere leere Methoden (mit dem Kommentar `// Herausforderung...`). Wer es mag, kann versuchen, an seinem Rechner diese Methoden zu definieren und auszuprobieren.
### Händisch testen ###
Probiere es mit Stift-und-Zettel und anhand von Beispielen die Werte händisch zu berechnen. Vergleiche dies mit den durch den Code rekursiv berechneten Werten. Stimmt alles überein?
### Automatisierte Tests ###
Wer etwas standardisierter seine Methoden testen will, kann automatisiertes Testing tätigen. Diese Tests existieren parallel zu jedem Modul und folgen dem Namensschema `..._test.go`.
- In der Console (wenn noch nicht geschehen) folgenden Befehl einmalig ausführen:
```bash
chmod +x test.sh
```
- In `aussagenlogik/rekursion/rekursion_test.go` beim relevanten Testteil eine oder mehrere der Zeilen
```go
test.Skip("Methode noch nicht implementiert")
```
rauskommentieren/löschen.
Jetzt `test.sh` ausführen. Die unittests testen Methoden gegen mehrere vorkonstruierte Testfälle samt erwarteten Ergebnissen geprüft. Sollten einige Tests scheitern, dann Fehlermeldung durchlesen, und Methode entsprechend der Kritik überarbeiten.
Die geschriebenen Unittests sind natürlich nicht ausführlich. Man kann diese nach Bedarf ergänzen. Am sinnvollsten baut man welche, die wirklich scheitern können, sonst sagen die Tests nichts aus.

View File

@ -0,0 +1,82 @@
package rekursion
import (
"log"
"logik/aussagenlogik/syntaxbaum"
"logik/core/utils"
)
/* ---------------------------------------------------------------- *
* EXPORTS
* ---------------------------------------------------------------- */
func RekursivEval(tree syntaxbaum.SyntaxBaum, I []string) int {
var children = tree.GetChildren()
switch tree.Kind {
case "atom", "generic":
if utils.StrListContains(I, tree.Expr) {
return 1
}
return 0
case "taut":
return 1
case "contradiction":
return 0
case "not":
subtree0, _ := tree.GetChild()
val0 := RekursivEval(subtree0, I)
return 1 - val0
case "and2":
val0 := RekursivEval(children[0], I)
val1 := RekursivEval(children[1], I)
return utils.Min2(val0, val1)
case "and":
var val = 1
for _, subtree := range children {
var val_ = RekursivEval(subtree, I)
val = utils.Min2(val, val_)
}
return val
case "or2":
val0 := RekursivEval(children[0], I)
val1 := RekursivEval(children[1], I)
return utils.Max2(val0, val1)
case "or":
var val = 0
for _, subtree := range children {
var val_ = RekursivEval(subtree, I)
val = utils.Max2(val, val_)
}
return val
case "implies":
val0 := RekursivEval(children[0], I)
val1 := RekursivEval(children[1], I)
if val0 <= val1 {
return 1
}
return 0
default:
log.Fatal("Could not evaluate expression!")
return 0
}
}
func RekursivAtoms(tree syntaxbaum.SyntaxBaum) []string {
// Herausforderung: schreibe diese Funktion!
return []string{}
}
func RekursivDepth(tree syntaxbaum.SyntaxBaum) int {
// Herausforderung: schreibe diese Funktion!
return 0
}
func RekursivLength(tree syntaxbaum.SyntaxBaum) int {
// Herausforderung: schreibe diese Funktion!
return 0
}
func RekursivParentheses(tree syntaxbaum.SyntaxBaum) int {
// Herausforderung: schreibe diese Funktion!
return 0
}

View File

@ -0,0 +1,287 @@
package rekursion_test
/* ---------------------------------------------------------------- *
* UNIT TESTING
* ---------------------------------------------------------------- */
import (
"logik/aussagenlogik/rekursion"
"logik/aussagenlogik/schema"
"logik/aussagenlogik/syntaxbaum"
"logik/core/utils"
"testing"
"github.com/stretchr/testify/assert"
)
/* ---------------------------------------------------------------- *
* TESTCASE eval(·, ·)
* ---------------------------------------------------------------- */
func TestRekursivEvalLiteral(test *testing.T) {
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var I []string
var val int
tree, _ = schema.ParseExpr("A0")
I = []string{"A0"}
val = rekursion.RekursivEval(tree, I)
assert.Equal(val, 1)
tree, _ = schema.ParseExpr("A0")
I = []string{}
val = rekursion.RekursivEval(tree, I)
assert.Equal(val, 0)
tree, _ = schema.ParseExpr("! A0")
I = []string{"A0"}
val = rekursion.RekursivEval(tree, I)
assert.Equal(val, 0)
tree, _ = schema.ParseExpr("! A0")
I = []string{}
val = rekursion.RekursivEval(tree, I)
assert.Equal(val, 1)
}
func TestRekursivEvalComplex1(test *testing.T) {
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var I []string
var val int
tree, _ = schema.ParseExpr("( ! A0 || (( A0 && A3 ) || A2 ))")
I = []string{"A0", "A2"}
val = rekursion.RekursivEval(tree, I)
assert.Equal(val, 1)
I = []string{"A0", "A3"}
val = rekursion.RekursivEval(tree, I)
assert.Equal(val, 1)
I = []string{"A0"}
val = rekursion.RekursivEval(tree, I)
assert.Equal(val, 0)
I = []string{"A4", "A8"}
val = rekursion.RekursivEval(tree, I)
assert.Equal(val, 1)
}
func TestRekursivEvalComplex2(test *testing.T) {
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var I []string
var val int
tree, _ = schema.ParseExpr("( ! A0 || (( A0 && A3 ) || ! A2 ))")
I = []string{"A0", "A2"}
val = rekursion.RekursivEval(tree, I)
assert.Equal(val, 0)
I = []string{"A0", "A3"}
val = rekursion.RekursivEval(tree, I)
assert.Equal(val, 1)
}
/* ---------------------------------------------------------------- *
* TESTCASE Atoms(·)
* ---------------------------------------------------------------- */
func TestRekursivAtomsNoduplicates(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var val []string
tree, _ = schema.ParseExpr("( A4 && ( A4 || A4 ))")
val = rekursion.RekursivAtoms(tree)
var n int = len(utils.FilterStrings(&val, func(x string) bool { return x == "A4" }))
assert.Equal(n, 1, "Atome dürfen nicht mehrfach vorkommen!")
}
func TestRekursivAtomsNononatoms(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
test.Skip("Syntax for generic expressions in ANTLR4 g4 needs to be implemented.")
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var val []string
tree, _ = schema.ParseExpr("( {F} || A3 )")
val = rekursion.RekursivAtoms(tree)
utils.SortStrings(&val)
assert.NotContains(val, "F", "Nichtatomare Formeln dürfen nicht vorkommen!")
}
func TestRekursivAtomsCalc1(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var val []string
tree, _ = schema.ParseExpr("A0")
val = rekursion.RekursivAtoms(tree)
utils.SortStrings(&val)
assert.Equal(val, []string{"A0"})
}
func TestRekursivAtomsCalc2(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var val []string
tree, _ = schema.ParseExpr("((( ! A8 && A3 ) || A4 ) && A0 )")
val = rekursion.RekursivAtoms(tree)
utils.SortStrings(&val)
assert.Equal(val, []string{"A0", "A3", "A4", "A8"})
}
/* ---------------------------------------------------------------- *
* TESTCASE depth(·, ·)
* ---------------------------------------------------------------- */
func TestRekursivDepthCalc1(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var val int
tree, _ = schema.ParseExpr("A0")
val = rekursion.RekursivDepth(tree)
assert.Equal(val, 0)
}
func TestRekursivDepthCalc2(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var val int
tree, _ = schema.ParseExpr("!! A8")
val = rekursion.RekursivDepth(tree)
assert.Equal(val, 2)
}
func TestRekursivDepthCalc3(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var val int
tree, _ = schema.ParseExpr("( ! A0 && A3 )")
val = rekursion.RekursivDepth(tree)
assert.Equal(val, 2)
}
func TestRekursivDepthCalc4(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var val int
tree, _ = schema.ParseExpr("((( ! A0 && A3 ) || A4 ) && A8 )")
val = rekursion.RekursivDepth(tree)
assert.Equal(val, 4)
}
func TestRekursivDepthCalc5(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var val int
tree, _ = schema.ParseExpr("! ((( ! A0 && A3 ) || A4 ) && A8 )")
val = rekursion.RekursivDepth(tree)
assert.Equal(val, 5)
}
/* ---------------------------------------------------------------- *
* TESTCASE length(·)
* ---------------------------------------------------------------- */
func TestRekursivLengthCalc1(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var val int
tree, _ = schema.ParseExpr("A0")
val = rekursion.RekursivLength(tree)
assert.Equal(val, 1)
}
func TestRekursivLengthCalc2(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var val int
tree, _ = schema.ParseExpr("!! A8")
val = rekursion.RekursivLength(tree)
assert.Equal(val, 3)
}
func TestRekursivLengthCalc3(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var val int
tree, _ = schema.ParseExpr("( ! A0 && A3 )")
val = rekursion.RekursivLength(tree)
assert.Equal(val, 4)
}
func TestRekursivLengthCalc4(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var val int
tree, _ = schema.ParseExpr("((( ! A0 && A3 ) || A4 ) && A8 )")
val = rekursion.RekursivLength(tree)
assert.Equal(val, 8)
}
func TestRekursivLengthCalc5(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var val int
tree, _ = schema.ParseExpr("! ((( ! A0 && A3 ) || A4 ) && A8 )")
val = rekursion.RekursivLength(tree)
assert.Equal(val, 9)
}
/* ---------------------------------------------------------------- *
* TESTCASE #Parentheses(·)
* ---------------------------------------------------------------- */
func TestRekursivParenthesesCalc1(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var val int
tree, _ = schema.ParseExpr("A0")
val = rekursion.RekursivParentheses(tree)
assert.Equal(val, 0)
}
func TestRekursivParenthesesCalc2(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var val int
tree, _ = schema.ParseExpr("!! A8")
val = rekursion.RekursivParentheses(tree)
assert.Equal(val, 0)
}
func TestRekursivParenthesesCalc3(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var val int
tree, _ = schema.ParseExpr("( ! A0 && A3 )")
val = rekursion.RekursivParentheses(tree)
assert.Equal(val, 2)
}
func TestRekursivParenthesesCalc4(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var val int
tree, _ = schema.ParseExpr("((( ! A0 && A3 ) || A4 ) && A8 )")
val = rekursion.RekursivParentheses(tree)
assert.Equal(val, 6)
}
func TestRekursivParenthesesCalc5(test *testing.T) {
test.Skip("Methode noch nicht implementiert")
var assert = assert.New(test)
var tree syntaxbaum.SyntaxBaum
var val int
tree, _ = schema.ParseExpr("! ((( ! A0 && A3 ) || A4 ) && A8 )")
val = rekursion.RekursivParentheses(tree)
assert.Equal(val, 6)
}

View File

@ -0,0 +1,175 @@
package schema
import (
"errors"
"logik/aussagenlogik/syntaxbaum"
parser "logik/grammars/aussagenlogik"
"strings"
"github.com/antlr/antlr4/runtime/Go/antlr"
)
/* ---------------------------------------------------------------- *
* EXPORTS
* ---------------------------------------------------------------- */
func ParseExpr(u string) (syntaxbaum.SyntaxBaum, error) {
var lexer = createLexer(u)
var tokenStream = lexerToTokenStream(lexer)
var prs = parser.NewaussagenlogikParser(tokenStream)
var t = prs.Start()
tree, err := createSyntaxBaum(t, prs)
return tree, err
}
/* ---------------------------------------------------------------- *
* 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 createSyntaxBaum(tree antlr.Tree, parser antlr.Parser) (syntaxbaum.SyntaxBaum, error) {
var ant = antlrTree{tree: tree, parser: &parser}
return ant.toSyntaxBaum()
}
/* ---------------------------------------------------------------- *
* 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) toSyntaxBaum() (syntaxbaum.SyntaxBaum, error) {
var tree syntaxbaum.SyntaxBaum
var err error
var label string = ant.getLabel()
var subants = ant.getChildren()
var nChildren = len(subants)
switch label {
case "start":
if nChildren == 1 {
return subants[0].toSyntaxBaum()
}
case "open":
if nChildren == 1 {
return subants[0].toSyntaxBaum()
}
case "closed":
switch nChildren {
case 1:
return subants[0].toSyntaxBaum()
case 3:
return subants[1].toSyntaxBaum()
}
case "atomic":
if nChildren == 1 {
subant := subants[0]
tree = syntaxbaum.SyntaxBaum{}
tree.Expr = subant.getTextContentLeaves()
tree.Kind = subant.getLabel()
tree.Children = [](*syntaxbaum.SyntaxBaum){}
tree.Valence = 0
return tree, nil
}
case "not":
if nChildren == 2 { // Children: [NotSymbol, Teilformel]
subtree, err := subants[1].toSyntaxBaum()
tree = syntaxbaum.SyntaxBaum{}
tree.Expr = subants[0].getTextContent() + " " + subtree.Expr
tree.Kind = label
tree.Children = [](*syntaxbaum.SyntaxBaum){&subtree}
tree.Valence = 1
return tree, err
}
case "and2", "and", "or2", "or", "implies":
var n int = int((len(subants) + 1) / 2)
if nChildren == 2*n-1 && n >= 2 {
var isSymb bool = false
var subtrees = make([](*syntaxbaum.SyntaxBaum), n)
var i int = 0
var expr string = ""
for _, subant := range subants {
if isSymb {
expr += " " + subant.getTextContent() + " "
} else {
subtree, err_ := subant.toSyntaxBaum()
if err_ != nil {
err = err_
}
subtrees[i] = &subtree
expr += " " + subtree.Expr + " "
i++
}
isSymb = !isSymb
}
expr = strings.Trim(expr, " ")
var lbrace string = "("
var rbrace string = ")"
// var lbrace string = "( "
// var rbrace string = " )"
// if strings.HasPrefix(expr, "(") {
// lbrace = "("
// }
// if strings.HasSuffix(expr, ")") {
// rbrace = ")"
// }
tree = syntaxbaum.SyntaxBaum{}
tree.Expr = lbrace + expr + rbrace
tree.Kind = label
tree.Children = subtrees
tree.Valence = n
return tree, err
}
}
return tree, errors.New("Could not parse expression")
}

View File

@ -0,0 +1,22 @@
package schema_test
/* ---------------------------------------------------------------- *
* UNIT TESTING
* ---------------------------------------------------------------- */
import (
"logik/aussagenlogik/schema"
"testing"
"github.com/stretchr/testify/assert"
)
/* ---------------------------------------------------------------- *
* TESTCASE ParseExpr
* ---------------------------------------------------------------- */
func TestParseExpr(test *testing.T) {
var assert = assert.New(test)
assert.Equal(0, 0)
schema.ParseExpr("A0")
}

View File

@ -0,0 +1,136 @@
package syntaxbaum
import (
"errors"
"fmt"
"strings"
)
type SyntaxBaum struct {
Kind string
Expr string
Valence int
Children [](*SyntaxBaum)
}
/* ---------------------------------------------------------------- *
* METHODS
* ---------------------------------------------------------------- */
func (tree SyntaxBaum) GetChildren() []SyntaxBaum {
var n int = tree.Valence
var children = make([]SyntaxBaum, n)
for i, subtreePtr := range tree.Children {
children[i] = *subtreePtr
}
return children
}
func (tree SyntaxBaum) GetChild(indexOpt ...int) (SyntaxBaum, error) {
var index int = 0
if len(indexOpt) > 0 {
index = indexOpt[0]
}
var subtree SyntaxBaum
var err error
if 0 <= index && index < tree.Valence {
subtree = *(tree.Children[index])
} else {
err = errors.New(fmt.Sprintf("Instance has no child of index %d !", index))
}
return subtree, err
}
func (tree SyntaxBaum) Pretty(preindentOpt ...string) string {
var preindent string = ""
if len(preindentOpt) > 0 {
preindent = preindentOpt[0]
}
return tree.pretty(preindent, " ", "", 0)
}
func (tree SyntaxBaum) pretty(preindent string, tab string, prepend string, depth int) string {
var indent string = preindent + strings.Repeat(tab, depth)
switch tree.Valence {
case 0:
switch kind := tree.Kind; kind {
case "atom", "generic":
return indent + prepend + kind + " " + tree.Expr
default:
return indent + prepend + kind
}
default:
var lines string = indent + prepend + tree.Kind
prepend = "|__ "
for _, subtree := range tree.Children {
lines += "\n" + subtree.pretty(preindent, tab, prepend, depth+1)
}
return lines
}
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// METHODS: Recognitong of Formula-Types
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
func (tree SyntaxBaum) isAtom() bool {
return tree.Kind == "atom"
}
func (tree SyntaxBaum) isLiteral() bool {
if tree.isAtom() {
return true
} else if tree.isNegation() {
subtree, err := tree.GetChild()
if err == nil {
return subtree.isAtom()
}
}
return false
}
func (tree SyntaxBaum) isBeliebig() bool {
return tree.Kind == "generic"
}
func (tree SyntaxBaum) isTrueSymbol() bool {
return tree.Kind == "taut"
}
func (tree SyntaxBaum) isFalseSymbol() bool {
return tree.Kind == "contradiction"
}
func (tree SyntaxBaum) isNegation() bool {
return tree.Kind == "not"
}
func (tree SyntaxBaum) isConjunction() bool {
return tree.Kind == "and2"
}
func (tree SyntaxBaum) isLongConjunction() bool {
switch tree.Kind {
case "and", "and2":
return true
default:
return false
}
}
func (tree SyntaxBaum) isDisjunction() bool {
return tree.Kind == "or2"
}
func (tree SyntaxBaum) isLongDisjunction() bool {
switch tree.Kind {
case "or", "or2":
return true
default:
return false
}
}
func (tree SyntaxBaum) isImplication() bool {
return tree.Kind == "implies"
}

View File

@ -0,0 +1,71 @@
package environment
import (
"errors"
"fmt"
"log"
"os"
"github.com/joho/godotenv"
)
var ENV_FILE_NAME string
/* ---------------------------------------------------------------- *
* EXPORTS
* ---------------------------------------------------------------- */
func ReadEnvKey(key string, optional ...string) string {
value, err := readEnvKey(key, optional...)
if err != nil {
log.Fatal(err)
}
return value
}
func ReadEnvKeyAllowMissing(key string, optional ...string) string {
value, _ := readEnvKey(key, optional...)
return value
}
func ReadEnvKeyDefault(key string, valueDefault string, optional ...string) string {
value, _ := readEnvKey(key, optional...)
if value == "" {
return valueDefault
}
return value
}
/* ---------------------------------------------------------------- *
* PRIVATE
* ---------------------------------------------------------------- */
func loadEnvFile(path string) error {
if path == "" {
log.Fatal("Path name to environment file is not allowed to be empty!")
}
return godotenv.Load(path)
}
func getEnvKey(key string) string {
return os.Getenv(key)
}
func readEnvKey(key string, optional ...string) (string, error) {
var path string = ENV_FILE_NAME
var err error
var value string
if len(optional) > 0 {
path = optional[0]
}
err = loadEnvFile(path)
if err != nil {
log.Fatalf("Could not read environment file, \033[1m%s\033[0m!\n", path)
}
err = nil
value = getEnvKey(key)
if value == "" {
err = errors.New(fmt.Sprintf("Environment key \033[1m%s\033[0m missing or empty in environment file \033[1m%s\033[0m!", key, path))
}
return value, err
}

View File

@ -0,0 +1,84 @@
package utils
import (
"sort"
"strings"
)
/* ---------------------------------------------------------------- *
* EXPORTS
* ---------------------------------------------------------------- */
func StrListContains(list []string, x string) bool {
for _, obj := range list {
if obj == x {
return true
}
}
return false
}
func Min2(x int, y int) int {
if x <= y {
return x
}
return y
}
func Max2(x int, y int) int {
if x >= y {
return x
}
return y
}
func SortStrings(list *[]string) {
sort.Slice(*list, func(i int, j int) bool {
u := strings.ToLower((*list)[i])
v := strings.ToLower((*list)[j])
cmp := strings.Compare(u, v)
return (cmp < 0)
})
}
func FilterStrings(list *[]string, f func(string) bool) []string {
var listFiltered = []string{}
for _, val := range *list {
if f(val) {
listFiltered = append(listFiltered, val)
}
}
return listFiltered
}
func UnionStrings2(list1 []string, list2 []string) []string {
var mark = make(map[string]bool)
for _, item := range list1 {
mark[item] = true
}
for _, item := range list2 {
mark[item] = true
}
var list = make([]string, len(mark))
var i int = 0
for item, _ := range mark {
list[i] = item
i++
}
return list
}
func UnionStringsTo(listTo *[]string, listFrom []string) {
var mark = make(map[string]bool)
for _, item := range listFrom {
mark[item] = true
}
for _, item := range *listTo {
mark[item] = false // signals suppression of duplicate addition
}
for item, isNew := range mark {
if isNew {
*listTo = append(*listTo, item)
}
}
}

View File

@ -0,0 +1,57 @@
package utils_test
/* ---------------------------------------------------------------- *
* UNIT TESTING
* ---------------------------------------------------------------- */
import (
"logik/core/utils"
"strings"
"testing"
"github.com/stretchr/testify/assert"
)
/* ---------------------------------------------------------------- *
* TESTCASE SortStrings
* ---------------------------------------------------------------- */
func TestSortStrings(test *testing.T) {
var assert = assert.New(test)
var list = []string{"katze", "Hund", "baby", "Pluto", "Saturn", "Mond"}
utils.SortStrings(&list)
assert.Equal(list, []string{"baby", "Hund", "katze", "Mond", "Pluto", "Saturn"})
}
/* ---------------------------------------------------------------- *
* TESTCASE SortStrings
* ---------------------------------------------------------------- */
func TestFilterStrings(test *testing.T) {
var assert = assert.New(test)
var list = []string{"abram", "aaron", "aardvark", "aarhus", "alaska", "eel", "aal"}
var list2 = utils.FilterStrings(&list, func(x string) bool { return strings.HasPrefix(x, "aa") })
assert.Equal(list2, []string{"aaron", "aardvark", "aarhus", "aal"})
}
/* ---------------------------------------------------------------- *
* TESTCASE UnionStrings2, UnionStringsTo
* ---------------------------------------------------------------- */
func TestUnionStrings2(test *testing.T) {
var assert = assert.New(test)
var list1 = []string{"red", "blue", "blue", "green", "blue", "grey", "black", "green"}
var list2 = []string{"yellow", "orange", "lila", "red"}
var list = utils.UnionStrings2(list1, list2)
utils.SortStrings(&list)
assert.Equal(list, []string{"black", "blue", "green", "grey", "lila", "orange", "red", "yellow"})
}
func UnionStringsTo(test *testing.T) {
var assert = assert.New(test)
var list1 = []string{"red", "blue", "blue", "green"}
var list2 = []string{"yellow", "red", "black"}
utils.UnionStringsTo(&list1, list2)
utils.SortStrings(&list1)
assert.Equal(list1, []string{"black", "blue", "green", "red", "yellow"})
}

12
codego/data.env Normal file
View File

@ -0,0 +1,12 @@
# expr = 'A0'
# expr = '! A0'
# expr = 'A9341'
# expr = '!!! A84'
# expr = '( A0 || A1 )'
# expr = '( A0 -> A1 )'
# expr = '( A0 && ! (0 || A8 || 1) ) -> A5'
expr = '( A0 -> ((A0 && A3 && A4) || ! A2) )'
# expr = '( A0 -> ((A0 && A3 && A4) || A2) )'
# expr = '( A0 -> ((A0 && A3) || A2) )'
# expr = '(( {G} || !{G} ) -> A5)'
interpretation = [ "A0", "A2" ]

13
codego/go.mod Normal file
View File

@ -0,0 +1,13 @@
module logik
go 1.16
require (
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210506161523-0a1c3e3ce1ca
github.com/joho/godotenv v1.3.0
github.com/lithammer/dedent v1.1.0
// siehe https://pkg.go.dev/github.com/stretchr/testify/assert
// und https://github.com/stretchr/testify
github.com/stretchr/testify v1.7.0
golang.org/x/tools v0.1.0
)

40
codego/go.sum Normal file
View File

@ -0,0 +1,40 @@
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210506161523-0a1c3e3ce1ca h1:cZZsTEHO/8dZcxfjctHHbnEDLKdvyjUjWLNchKdgO94=
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210506161523-0a1c3e3ce1ca/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/lithammer/dedent v1.1.0 h1:VNzHMVCBNG1j0fh3OrsFRkVUwStdDArbgBWoPAffktY=
github.com/lithammer/dedent v1.1.0/go.mod h1:jrXYCQtgg0nJiN+StA2KgR7w6CiQNv9Fd/Z9BP0jIOc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -0,0 +1,5 @@
# ANTLR4 #
Gebrauchsanleitung <https://blog.gopheracademy.com/advent-2017/parsing-with-antlr4-and-go>
_Hinweis:_ In dieser Repo wurden die in der o.s. Webseite erwähnten Schritte bereits in den bash Skripten berücksichtigt.

95
codego/main.go Normal file
View File

@ -0,0 +1,95 @@
package main
import (
"encoding/json"
"fmt"
"logik/aussagenlogik/rekursion"
"logik/aussagenlogik/schema"
"logik/aussagenlogik/syntaxbaum"
env "logik/core/environment"
"strings"
"github.com/lithammer/dedent"
)
var DATA_ENV string = "data.env"
type dataType struct {
expr string
interpretation []string
}
type resultsType struct {
eval int
atoms []string
depth int
length int
nParentheses int
}
var data dataType
func main() {
// Extrahiere Daten
err := getData()
if err != nil {
return
}
// Ausdruck -> Syntaxbaum
tree, err := schema.ParseExpr(data.expr)
if err != nil {
return
}
// Methoden ausführen:
results := resultsType{
eval: rekursion.RekursivEval(tree, data.interpretation),
atoms: rekursion.RekursivAtoms(tree),
depth: rekursion.RekursivDepth(tree),
length: rekursion.RekursivLength(tree),
nParentheses: rekursion.RekursivParentheses(tree),
}
// Resultate anzeigen:
displayResults(tree, results)
}
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SONSTIGE METHODEN
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
func getData() error {
env.ENV_FILE_NAME = DATA_ENV
data.expr = env.ReadEnvKey("expr")
s := env.ReadEnvKey("interpretation")
err := json.Unmarshal([]byte(s), &data.interpretation)
return err
}
func displayResults(tree syntaxbaum.SyntaxBaum, results resultsType) {
fmt.Println(fmt.Sprintf(
dedent.Dedent(`
Syntaxbaum von
F := %[1]s:
%[2]s
Für I = {%[3]s} und F wie oben gilt
eval(F, I) = %[4]d;
atoms(F) = {%[5]s}; <- *
depth(F) = %[6]d; <- *
length(F) = %[7]d; <- *
#parentheses(F) = %[8]d; <- *
* noch nicht implementiert!
Challenge: schreibe diese Methoden! (siehe README.md)
`),
tree.Expr,
tree.Pretty(" "),
strings.Join(data.interpretation, ", "),
results.eval,
// string(results.atoms),
strings.Join(results.atoms, ", "),
results.depth,
results.length,
results.nParentheses,
))
}

54
codego/run.sh Executable file
View File

@ -0,0 +1,54 @@
#!/usr/bin/env bash
################################################################################################
# NOTE: `chmod +x run.sh` vorher ausführen, um dieses Skript benutzen zu können.
################################################################################################
################################
# HILFSMETHODEN
################################
function call_go() {
go $@;
}
function check_requirements() {
[ -f "go.sum" ] && rm "go.sum";
call_go get "$( cat requirements )";
}
function precompile_grammars() {
local fname;
local name;
pushd grammars >> /dev/null;
while read fname; do
( [ "$fname" == "" ] || ! [ -f "$fname" ] ) && continue;
name="$( echo "$fname" | sed -E "s/^(.*)\.g4$/\1/g" )";
echo -e "\033[92;1mANTLR4\033[0m präkompiliert Grammatik \033[1m${fname}\033[0m";
java -jar antlr.jar -Dlanguage=Go "$fname" -o "$name";
done <<< "$( ls *.g4 2> /dev/null )"
popd >> /dev/null
}
function compile_programme() {
[ -f "main" ] && rm "main";
echo -e "\033[92;1mGO\033[0m kompiliert \033[1mmain.go\033[0m";
call_go build "main.go";
}
function run_programme() {
echo -e "\033[92;1mGO\033[0m kompiliertes Programm wird ausgeführt";
./main;
}
################################
# HAUPTVORGÄNGE
################################
# Kann auskommentiert werden, wenn nötige Module schon installiert:
check_requirements;
# Code als Programm kompilieren und ausführen:
precompile_grammars;
compile_programme;
run_programme;

33
codego/test.sh Executable file
View File

@ -0,0 +1,33 @@
#!/usr/bin/env bash
################################################################################################
# NOTE: `chmod +x test.sh` vorher ausführen, um dieses Skript benutzen zu können.
################################################################################################
################################
# HILFSMETHODEN
################################
function call_go() {
go $@;
}
function check_requirements() {
[ -f "go.sum" ] && rm "go.sum";
call_go get "$( cat requirements )";
}
function run_unittests(){
echo -e "\033[1mUNITTESTS\033[0m\n";
call_go test -v -timeout 60s -count 1 -run "^Test[A-Z].*" "logik" "./...";
}
################################
# HAUPTVORGÄNGE
################################
# Kann auskommentiert werden, wenn nötige Module schon installiert:
check_requirements;
# Code testen (unittests):
run_unittests;