diff options
Diffstat (limited to 'cmd/la-baujmi/fact.go')
| -rw-r--r-- | cmd/la-baujmi/fact.go | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/cmd/la-baujmi/fact.go b/cmd/la-baujmi/fact.go new file mode 100644 index 0000000..a421d1e --- /dev/null +++ b/cmd/la-baujmi/fact.go @@ -0,0 +1,210 @@ +package main + +import ( + "errors" + "strings" + + "github.com/Xe/x/web/tokiponatokens" +) + +// Selbri is a predicate relationship between its arguments. The name comes from +// the lojban term selbri: http://jbovlaste.lojban.org/dict/selbri. +type Selbri struct { + Predicate string + Arguments []string +} + +// Fact converts a selbri into a prolog fact. +func (s Selbri) Fact() string { + var sb strings.Builder + + var varCount byte + + sb.WriteString("selbri(verb(") + + if s.Predicate == "seme" { + sb.WriteByte(byte('A') + varCount) + varCount++ + } else { + sb.WriteString(s.Predicate) + } + sb.WriteString("), ") + + for i, arg := range s.Arguments { + if i != 0 { + sb.WriteString(", ") + } + + switch arg { + case "subject(seme)", "object(seme)": + if strings.HasPrefix(arg, "subject") { + sb.WriteString("subject(") + } else { + sb.WriteString("object(") + } + sb.WriteByte(byte('A') + varCount) + varCount++ + sb.WriteByte(')') + continue + } + sb.WriteString(arg) + } + + sb.WriteString(").") + return sb.String() +} + +var ( + // ErrNoPredicate is raised when the given sentence does not have a verb. + // This is a side effect of the way we are potentially misusing prolog + // here. + ErrNoPredicate = errors.New("la-baujmi: sentence must have a verb to function as the logical predicate") +) + +// SentenceToSelbris creates logical facts derived from toki pona sentences. +// This is intended to be the first step in loading them into prolog. +func SentenceToSelbris(s tokiponatokens.Sentence) ([]Selbri, error) { + var ( + subjects []string + verbs []string + objects []string + context string + ) + + for _, pt := range s { + switch pt.Type { + case tokiponatokens.PartSubject: + if strings.Contains(pt.Braces(), " en ") { + temp := strings.Split(strings.Join(pt.Tokens, " "), " en ") + + for _, t := range temp { + subjects = append(subjects, "subject("+t+")") + } + + continue + } + + if len(pt.Parts) != 0 { + var sb strings.Builder + sb.WriteString("subject(") + + for i, sp := range pt.Parts { + if i != 0 { + sb.WriteString(", ") + } + if sp.Sep != nil && *sp.Sep == "pi" { + sb.WriteString("pi(") + for j, tk := range sp.Tokens { + if j != 0 { + sb.WriteString(", ") + } + + sb.WriteString(tk) + } + sb.WriteString(")") + } else { + sb.WriteString(strings.Join(sp.Tokens, "_")) + } + } + + sb.WriteString(")") + + subjects = append(objects, sb.String()) + continue + } + + subjects = append(subjects, "subject("+strings.Join(pt.Tokens, "_")+")") + + case tokiponatokens.PartVerbMarker: + verbs = append(verbs, strings.Join(pt.Tokens, "_")) + + case tokiponatokens.PartObjectMarker: + if len(pt.Parts) != 0 { + var sb strings.Builder + sb.WriteString("object(") + + for i, sp := range pt.Parts { + if i != 0 { + sb.WriteString(", ") + } + if sp.Sep != nil && *sp.Sep == "pi" { + sb.WriteString("pi(") + for j, tk := range sp.Tokens { + if j != 0 { + sb.WriteString(", ") + } + + sb.WriteString(tk) + } + sb.WriteString(")") + } else { + sb.WriteString(strings.Join(sp.Tokens, "_")) + } + } + + sb.WriteString(")") + + objects = append(objects, sb.String()) + continue + } + objects = append(objects, "object("+strings.Join(pt.Tokens, "_")+")") + + case tokiponatokens.PartPunctuation: + if len(pt.Tokens) == 1 { + switch pt.Tokens[0] { + case "la": + context = "context(" + subjects[len(subjects)-1] + ")" + subjects = subjects[:len(subjects)-1] + + case tokiponatokens.PunctComma: + return nil, errors.New("please avoid commas in this function") + } + } + } + } + + if len(verbs) == 0 { + return nil, ErrNoPredicate + } + + var result []Selbri + + for _, v := range verbs { + for _, s := range subjects { + if len(objects) == 0 { + // sumti: x1 is a/the argument of predicate function x2 filling place x3 (kind/number) + var sumti []string + if context != "" { + sumti = append([]string{}, context) + } + sumti = append(sumti, s) + + r := Selbri{ + Predicate: v, + Arguments: sumti, + } + + result = append(result, r) + } + + for _, o := range objects { + // sumti: x1 is a/the argument of predicate function x2 filling place x3 (kind/number) + var sumti []string + if context != "" { + sumti = append([]string{}, context) + } + sumti = append(sumti, s) + sumti = append(sumti, o) + + r := Selbri{ + Predicate: v, + Arguments: sumti, + } + + result = append(result, r) + } + } + } + + return result, nil +} |
