Skip to content

Commit

Permalink
add project to version control
Browse files Browse the repository at this point in the history
  • Loading branch information
xenomote committed Oct 17, 2022
0 parents commit f81dea2
Show file tree
Hide file tree
Showing 14 changed files with 1,675 additions and 0 deletions.
Empty file added .gitignore
Empty file.
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/xenomote/object_language

go 1.19
Empty file added go.sum
Empty file.
40 changes: 40 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package main

import (
"fmt"
"log"

"github.com/xenomote/object_language/pattern"
)

func main() {
p, err := pattern.Parse(`
{
"type": "event.source",
"data": {
"metadata": <=x> {
"set": null
}
}
}
`)
if err != nil {
log.Fatalln(err)
}

b, err := p.Interpret(`
{
"type": "event.source",
"data": {
"metadata": {
"set": "null"
}
}
}
`)
if err != nil {
log.Fatalln(err)
}

fmt.Println(b)
}
112 changes: 112 additions & 0 deletions pattern/array.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package pattern

import (
"encoding/json"
"fmt"
)

func (a Array) Interpret(s string) (bindings map[string]string, err error) {
return a.Match(s, map[string]string{})
}

func (a Array) Match(s string, old_bindings map[string]string) (new_bindings map[string]string, err error) {
new_bindings = map[string]string{}

bindings := map[string]string{}
for k, v := range old_bindings {
bindings[k] = v
}

var input []json.RawMessage
err = json.Unmarshal([]byte(s), &input)
if err != nil {
input := "input"
if len(s) < 10 {
input = "\"" + s + "\""
}

return nil, fmt.Errorf("%s could not be interpreted as an array: %w", input, err)
}

for _, definition := range a.Definitions {
index, err := definition.Index.Index()
if err != nil {
return nil, err
}

prefix := ""
if definition.Index.String() != fmt.Sprint(index) {
prefix = definition.Index.String() + " = "
}

if index >= len(input) {
if definition.Optional {
continue
} else {
return nil, fmt.Errorf("array was not long enough to contain required index %s%d", prefix, index)
}
}

value := input[index]
matched_bindings, err := definition.Assignment.Match(string(value), bindings)
if err != nil {
return nil, fmt.Errorf("could not match index %s%d: %s", prefix, index, err)
}

for k, v := range matched_bindings {
if _, k_exists := bindings[k]; k_exists {
return nil, fmt.Errorf("binding for %s already exists and cannot be overwritten", k)
}

bindings[k] = v
new_bindings[k] = v
}
}

return new_bindings, nil
}

func (a Array) Validate(bindings map[string]bool) error {
indices := make(map[string]bool)
for _, d := range a.Definitions {
if _, exists := indices[d.Index.String()]; exists {
return fmt.Errorf("duplicate index %s", d.Index.String())
}

indices[d.Index.String()] = true
}

for _, d := range a.Definitions {
if err := d.Validate(bindings); err != nil {
return fmt.Errorf("at index %s: %s", d.Index, err)
}
}

return nil
}

func (a Array) String() string {
s := "["

for i, definition := range a.Definitions {
s += "\n" + indent(definition.String())

if i < len(a.Definitions)-1 {
s += ","
} else {
s += "\n"
}
}

s += "]"

return s
}

func (o ArrayDefinition) String() string {
op := ""
if o.Optional {
op = "?"
}
return o.Index.String() + op + ": " + o.Assignment.String()
}
20 changes: 20 additions & 0 deletions pattern/binding.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package pattern

import "fmt"

func (b Binding) Match(s string, bindings map[string]string) (map[string]string, error) {
return map[string]string{string(b): s}, nil
}

func (b Binding) Validate(bindings map[string]bool) error {
if _, exists := bindings[string(b)]; exists {
return fmt.Errorf("duplicate binding %s", b)
}

bindings[string(b)] = true
return nil
}

func (b Binding) String() string {
return "<=" + string(b) + ">"
}
Loading

0 comments on commit f81dea2

Please sign in to comment.