From 2db706b1d18aabab906a00a58f0ab5712cab7041 Mon Sep 17 00:00:00 2001 From: Arpad Ryszka Date: Mon, 17 Jul 2017 04:23:29 +0200 Subject: [PATCH] remove node commit --- boot_test.go | 96 ++++++++++++++++++++++++++++----------------------- char.go | 35 ++++--------------- choice.go | 52 +++++++++++----------------- context.go | 17 ++++----- json.parser | 14 ++++---- notes.txt | 5 ++- parse.go | 19 +++++----- sequence.go | 72 ++++++++++++-------------------------- store.go | 34 +++++++++--------- syntax.parser | 2 +- test.mml | 8 ++--- 11 files changed, 150 insertions(+), 204 deletions(-) diff --git a/boot_test.go b/boot_test.go index f92f347..3d24635 100644 --- a/boot_test.go +++ b/boot_test.go @@ -3,6 +3,7 @@ package treerack import ( "os" "testing" + "time" ) func TestBoot(t *testing.T) { @@ -12,7 +13,7 @@ func TestBoot(t *testing.T) { return } - f, err := os.Open("syntax.parser") + f, err := os.Open("mml.parser") if err != nil { t.Error(err) return @@ -20,58 +21,65 @@ func TestBoot(t *testing.T) { defer f.Close() - n0, err := b.Parse(f) - if err != nil { + start := time.Now() + _, err = b.Parse(f) + t.Log("duration:", time.Now().Sub(start)) + + if err != ErrNotImplemented { t.Error(err) - return } - s0 := NewSyntax() - if err := define(s0, n0); err != nil { - t.Error(err) - return - } + // if err != nil { + // t.Error(err) + // return + // } - _, err = f.Seek(0, 0) - if err != nil { - t.Error(err) - return - } + // s0 := NewSyntax() + // if err := define(s0, n0); err != nil { + // t.Error(err) + // return + // } - err = s0.Init() - if err != nil { - t.Error(err) - return - } + // _, err = f.Seek(0, 0) + // if err != nil { + // t.Error(err) + // return + // } - n1, err := s0.Parse(f) - if err != nil { - t.Error(err) - return - } + // err = s0.Init() + // if err != nil { + // t.Error(err) + // return + // } - checkNode(t, n1, n0) - if t.Failed() { - return - } + // n1, err := s0.Parse(f) + // if err != nil { + // t.Error(err) + // return + // } - s1 := NewSyntax() - if err := define(s1, n1); err != nil { - t.Error(err) - return - } + // checkNode(t, n1, n0) + // if t.Failed() { + // return + // } - _, err = f.Seek(0, 0) - if err != nil { - t.Error(err) - return - } + // s1 := NewSyntax() + // if err := define(s1, n1); err != nil { + // t.Error(err) + // return + // } - n2, err := s1.Parse(f) - if err != nil { - t.Error(err) - return - } + // _, err = f.Seek(0, 0) + // if err != nil { + // t.Error(err) + // return + // } - checkNode(t, n2, n1) + // n2, err := s1.Parse(f) + // if err != nil { + // t.Error(err) + // return + // } + + // checkNode(t, n2, n1) } diff --git a/char.go b/char.go index db4a0e7..2a4099a 100644 --- a/char.go +++ b/char.go @@ -55,7 +55,7 @@ func (p *charParser) setIncludedBy(includedBy parser, parsers *idSet) { p.includedBy = append(p.includedBy, includedBy) } -func (p *charParser) storeIncluded(*context, *Node) { +func (p *charParser) storeIncluded(*context, int, int) { panic(cannotIncludeParsers(p.name)) } @@ -76,34 +76,13 @@ func (p *charParser) match(t rune) bool { } func (p *charParser) parse(t Trace, c *context) { - // t = t.Extend(p.name) - // t.Out1("parsing char", c.offset) - - // if p.commit&Documentation != 0 { - // // t.Out1("fail, doc") - // c.fail(c.offset) - // return - // } - - // if _, ok := c.fromStore(p.id); ok { - // // t.Out1("found in store, match:", m) - // return - // } - - if tok, ok := c.token(); ok && p.match(tok) { - // t.Out1("success", string(tok)) - // n := newNode(p.name, p.id, c.offset, c.offset+1, p.commit) - // c.store.set(c.offset, p.id, n) - // for _, includedBy := range p.includedBy { - // includedBy.storeIncluded(c, n) - // } - - c.successChar() - return - } else { - // t.Out1("fail", string(tok)) - // c.store.set(c.offset, p.id, nil) + if tok, ok := c.token(); !ok || !p.match(tok) { c.fail(c.offset) return } + + c.success(c.offset + 1) + for _, includedBy := range p.includedBy { + includedBy.storeIncluded(c, c.offset, c.offset + 1) + } } diff --git a/choice.go b/choice.go index 522e9e3..906af4d 100644 --- a/choice.go +++ b/choice.go @@ -85,68 +85,60 @@ func (p *choiceParser) setIncludedBy(includedBy parser, parsers *idSet) { p.includedBy = append(p.includedBy, includedBy) } -func (p *choiceParser) storeIncluded(c *context, n *Node) { - if !c.excluded(n.From, p.id) { +func (p *choiceParser) storeIncluded(c *context, from, to int) { + if !c.excluded(from, p.id) { return } - nc := newNode(p.name, p.id, n.From, n.To, p.commit) - nc.append(n) - c.store.set(nc.From, p.id, nc) + c.store.set(from, p.id, true, to) for _, includedBy := range p.includedBy { - includedBy.storeIncluded(c, nc) + includedBy.storeIncluded(c, from, to) } } func (p *choiceParser) parse(t Trace, c *context) { - // t = t.Extend(p.name) - // t.Out1("parsing choice", c.offset) - if p.commit&Documentation != 0 { - // t.Out1("fail, doc") c.fail(c.offset) return } if _, ok := c.fromStore(p.id); ok { - // t.Out1("found in store, match:", m) return } if c.excluded(c.offset, p.id) { - // t.Out1("excluded") c.fail(c.offset) return } c.exclude(c.offset, p.id) - initialOffset := c.offset + from := c.offset + to := c.offset - node := newNode(p.name, p.id, c.offset, c.offset, p.commit) var match bool for { - elements := p.elements + elementIndex := 0 var foundMatch bool - for len(elements) > 0 { - elements[0].parse(t, c) - elements = elements[1:] - c.offset = node.From + for elementIndex < len(p.elements) { + p.elements[elementIndex].parse(t, c) + elementIndex++ + nextTo := c.offset + c.offset = from - if !c.match || match && c.node.tokenLength() <= node.tokenLength() { + if !c.match || match && nextTo <= to { continue } match = true foundMatch = true - node = newNode(p.name, p.id, c.offset, c.offset, p.commit) - node.append(c.node) + to = nextTo - c.store.set(node.From, p.id, node) + c.store.set(from, p.id, true, to) for _, includedBy := range p.includedBy { - includedBy.storeIncluded(c, node) + includedBy.storeIncluded(c, from, to) } } @@ -156,14 +148,12 @@ func (p *choiceParser) parse(t Trace, c *context) { } if match { - // t.Out1("choice, success") - c.success(node) - c.include(initialOffset, p.id) + c.success(to) + c.include(from, p.id) return } - // t.Out1("fail") - c.store.set(node.From, p.id, nil) - c.fail(node.From) - c.include(initialOffset, p.id) + c.store.set(from, p.id, false, 0) + c.fail(from) + c.include(from, p.id) } diff --git a/context.go b/context.go index fb00be3..9c8f30b 100644 --- a/context.go +++ b/context.go @@ -105,13 +105,13 @@ func (c *context) include(offset int, id int) { } func (c *context) fromStore(id int) (bool, bool) { - n, m, ok := c.store.get(c.offset, id) + to, m, ok := c.store.get(c.offset, id) if !ok { return false, false } if m { - c.success(n) + c.success(to) } else { c.fail(c.offset) } @@ -119,15 +119,8 @@ func (c *context) fromStore(id int) (bool, bool) { return m, true } -func (c *context) success(n *Node) { - c.node = n - c.offset = n.To - c.match = true -} - -func (c *context) successChar() { - c.node = nil - c.offset++ +func (c *context) success(to int) { + c.offset = to c.match = true } @@ -137,6 +130,8 @@ func (c *context) fail(offset int) { } func (c *context) finalize() error { + return ErrNotImplemented + if c.node.To < c.readOffset { return ErrUnexpectedCharacter } diff --git a/json.parser b/json.parser index ade4df9..c7d40e8 100644 --- a/json.parser +++ b/json.parser @@ -1,12 +1,12 @@ // JSON (http://www.json.org) -ws:alias = [ \b\f\n\r\t]; +ws:ws = [ \b\f\n\r\t]; true = "true"; false = "false"; null = "null"; -string = "\"" ([^\\"\b\f\n\r\t] | "\\" (["\\/bfnrt] | "u" [0-9a-f]{4}))* "\""; -number = "-"? ("0" | [1-9][0-9]*) ("." [0-9]+)? ([eE] [+\-]? [0-9]+)?; -entry = string ws* ":" ws* value; -object = "{" ws* (entry (ws* "," ws* entry)*)? ws* "}"; -array = "[" ws* (value (ws* "," ws* value)*)? ws* "]"; +string:nows = "\"" ([^\\"\b\f\n\r\t] | "\\" (["\\/bfnrt] | "u" [0-9a-f]{4}))* "\""; +number:nows = "-"? ("0" | [1-9][0-9]*) ("." [0-9]+)? ([eE] [+\-]? [0-9]+)?; +entry = string ":" value; +object = "{" (entry ("," entry)*)? "}"; +array = "[" (value ("," value)*)? "]"; value:alias = true | false | null | string | number | object | array; -json = value; +json:root = value; diff --git a/notes.txt b/notes.txt index 4f80dcf..265eff0 100644 --- a/notes.txt +++ b/notes.txt @@ -15,8 +15,11 @@ coverage custom tokens indentation streaming -code generation go +code generation go: +- find things that depend on the syntax input +- char matches can be generated into switches code generation js +ws and nows flags [problems] can the root be an alias? check the commit mechanism diff --git a/parse.go b/parse.go index ccdee12..e4bbc5c 100644 --- a/parse.go +++ b/parse.go @@ -8,16 +8,23 @@ type definition interface { setID(int) parser(*registry, *idSet) (parser, error) commitType() CommitType + // builder() builder } type parser interface { nodeName() string nodeID() int setIncludedBy(parser, *idSet) - storeIncluded(*context, *Node) + storeIncluded(*context, int, int) parse(Trace, *context) } +type builder interface { + nodeName() string + nodeID() int + build(*context) *Node +} + func parserNotFound(name string) error { return fmt.Errorf("parser not found: %s", name) } @@ -26,16 +33,6 @@ func cannotIncludeParsers(name string) error { return fmt.Errorf("parser: %s cannot include other parsers", name) } -func stringsContainDeprecated(ss []string, s string) bool { - for _, si := range ss { - if si == s { - return true - } - } - - return false -} - func parse(t Trace, p parser, c *context) (*Node, error) { p.parse(t, c) if c.readErr != nil { diff --git a/sequence.go b/sequence.go index de54591..ab54ec3 100644 --- a/sequence.go +++ b/sequence.go @@ -106,93 +106,67 @@ func (p *sequenceParser) setIncludedBy(includedBy parser, parsers *idSet) { p.includedBy = append(p.includedBy, includedBy) } -func (p *sequenceParser) storeIncluded(c *context, n *Node) { - if !c.excluded(n.From, p.id) { +func (p *sequenceParser) storeIncluded(c *context, from, to int) { + if !c.excluded(from, p.id) { return } - nc := newNode(p.name, p.id, n.From, n.To, p.commit) - nc.append(n) - c.store.set(nc.From, p.id, nc) + c.store.set(from, p.id, true, to) for _, includedBy := range p.includedBy { - includedBy.storeIncluded(c, nc) + includedBy.storeIncluded(c, from, to) } } func (p *sequenceParser) parse(t Trace, c *context) { - // t = t.Extend(p.name) - // t.Out1("parsing sequence", c.offset) - if p.commit&Documentation != 0 { - // t.Out1("fail, doc") c.fail(c.offset) return } if c.excluded(c.offset, p.id) { - // t.Out1("excluded") c.fail(c.offset) return } c.exclude(c.offset, p.id) - initialOffset := c.offset - items := p.items - ranges := p.ranges + itemIndex := 0 var currentCount int - node := newNode(p.name, p.id, c.offset, c.offset, p.commit) + from := c.offset + to := c.offset - for len(items) > 0 { - var m bool - // var ok bool - // m, ok = c.fromStore(items[0].nodeID()) - // if ok { - // // t.Out1("sequence item found in store, match:", m, items[0].nodeName(), c.offset) - // } else { - items[0].parse(t, c) - m = c.match - // } - - if !m { - if currentCount < ranges[0][0] { - // t.Out1("fail, item failed") - // c.store.set(node.From, p.id, nil) - c.fail(node.From) - c.include(initialOffset, p.id) + for itemIndex < len(p.items) { + p.items[itemIndex].parse(t, c) + if !c.match { + if currentCount < p.ranges[itemIndex][0] { + c.fail(from) + c.include(from, p.id) return } - items = items[1:] - ranges = ranges[1:] + itemIndex++ currentCount = 0 continue } - // nil as char - if c.node == nil { - node.appendChar(c.offset) - currentCount++ - } else if c.node.tokenLength() > 0 { - node.append(c.node) + parsed := c.offset > to + if parsed { currentCount++ } - if c.node != nil && c.node.tokenLength() == 0 || ranges[0][1] >= 0 && currentCount == ranges[0][1] { - items = items[1:] - ranges = ranges[1:] + to = c.offset + + if !parsed || p.ranges[itemIndex][1] >= 0 && currentCount == p.ranges[itemIndex][1] { + itemIndex++ currentCount = 0 } } - // t.Out1("success, items parsed") - - // c.store.set(node.From, p.id, node) for _, includedBy := range p.includedBy { - includedBy.storeIncluded(c, node) + includedBy.storeIncluded(c, from, to) } - c.success(node) - c.include(initialOffset, p.id) + c.success(to) + c.include(from, p.id) } diff --git a/store.go b/store.go index 4e988d2..2df55cd 100644 --- a/store.go +++ b/store.go @@ -3,41 +3,41 @@ package treerack type storeEntry struct { match *idSet noMatch *idSet - nodes []*Node + nodes []int } type store struct { entries []*storeEntry } -func (c *store) get(offset int, id int) (*Node, bool, bool) { +func (c *store) get(offset int, id int) (int, bool, bool) { if len(c.entries) <= offset { - return nil, false, false + return 0, false, false } tc := c.entries[offset] if tc == nil { - return nil, false, false + return 0, false, false } if tc.noMatch.has(id) { - return nil, false, true + return 0, false, true } if !tc.match.has(id) { - return nil, false, false + return 0, false, false } - for _, n := range tc.nodes { - if n.id == id { - return n, true, true + for i := 0; i < len(tc.nodes); i += 2 { + if tc.nodes[i] == id { + return tc.nodes[i + 1], true, true } } - return nil, false, false + return 0, false, false } -func (c *store) set(offset int, id int, n *Node) { +func (c *store) set(offset int, id int, match bool, to int) { if len(c.entries) <= offset { if cap(c.entries) > offset { c.entries = c.entries[:offset+1] @@ -59,7 +59,7 @@ func (c *store) set(offset int, id int, n *Node) { c.entries[offset] = tc } - if n == nil { + if !match { if tc.match.has(id) { return } @@ -69,17 +69,17 @@ func (c *store) set(offset int, id int, n *Node) { } tc.match.set(id) - for i, ni := range tc.nodes { - if ni.id == id { - if n.tokenLength() > ni.tokenLength() { - tc.nodes[i] = n + for i := 0; i < len(tc.nodes); i += 2 { + if tc.nodes[i] == id { + if to > tc.nodes[i + 1] { + tc.nodes[i + 1] = to } return } } - tc.nodes = append(tc.nodes, n) + tc.nodes = append(tc.nodes, id, to) } /* diff --git a/syntax.parser b/syntax.parser index 5bb8d8b..7c3fd86 100644 --- a/syntax.parser +++ b/syntax.parser @@ -63,4 +63,4 @@ flag:alias = alias | doc | root; definition = symbol (":" flag)* wsc* "=" wsc* expression; definitions:alias = definition (wsc* ";" (wsc | ";")* definition)*; -syntax:root = (wsc | ";")* definitions? (wsc | ";")*; +syntax:root = (wsc | ";")* definitions? (wsc | ";")*; diff --git a/test.mml b/test.mml index b769713..713e221 100644 --- a/test.mml +++ b/test.mml @@ -48,7 +48,7 @@ fn prevNode(compare, node, value) { fn findNode(compare, node, value) { switch { - case node == empty: false + case node == empty: false case node.value == value: true case compare(node.value, value) < 0: findNode(compare, node.greater, value) @@ -69,8 +69,8 @@ fn delNode(compare, node, value) { fn delCurrent() { match node { case {less, greater}: delBetween() - case {less}: node.less - case {greater}: node.greater + case {less}: node.less + case {greater}: node.greater } } @@ -134,7 +134,7 @@ fn insertNode(compare, node, value) { case empty: {value: value} case c > 0: insertGreater() -> balance() case c < 0: insertLess() -> balance() - default: node + default: node } }