From e0c51c3695b02c69100bc0f4a70a35703d62459a Mon Sep 17 00:00:00 2001 From: Markus Zimmermann Date: Thu, 26 Jun 2014 12:03:06 +0200 Subject: [PATCH] rename unrollLoops to UnrollPointers and move it --- parser/tavor.go | 145 ++----------------------------------------- parser/tavor_test.go | 15 ++--- tavor.go | 137 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 149 insertions(+), 148 deletions(-) diff --git a/parser/tavor.go b/parser/tavor.go index 237dedf..c026794 100644 --- a/parser/tavor.go +++ b/parser/tavor.go @@ -30,10 +30,6 @@ import ( const zeroRune = 0 -const ( - MaxRepeat = 2 -) - type tokenUse struct { token token.Token position scanner.Position @@ -328,7 +324,7 @@ OUT: var from, to int if sym == '*' { - from, to = 0, MaxRepeat + from, to = 0, tavor.MaxRepeat } else { if c == scanner.Int { from, _ = strconv.Atoi(p.scan.TokenText()) @@ -341,7 +337,7 @@ OUT: // until there is an explicit "to" we can assume to==from to = from } else { - from, to = 1, MaxRepeat + from, to = 1, tavor.MaxRepeat } if c == ',' { @@ -358,7 +354,7 @@ OUT: fmt.Printf("parseTerm repeat after to ( %d:%v -> %v\n", p.scan.Line, scanner.TokenString(c), p.scan.TokenText()) } } else { - to = MaxRepeat + to = tavor.MaxRepeat } } } @@ -1109,139 +1105,6 @@ func (p *tavorParser) parseSpecialTokenDefinition() (rune, error) { return c, nil } -func (p *tavorParser) unrollLoops(root token.Token) token.Token { - type unrollToken struct { - tok token.Token - parent *unrollToken - } - - if tavor.DEBUG { - fmt.Println("Unroll loops by cloning pointers") - } - - checked := make(map[token.Token]token.Token) - counters := make(map[token.Token]int) - - queue := linkedlist.New() - - queue.Push(&unrollToken{ - tok: root, - parent: nil, - }) - - for !queue.Empty() { - v, _ := queue.Shift() - iTok, _ := v.(*unrollToken) - - switch t := iTok.tok.(type) { - case *primitives.Pointer: - o := t.InternalGet() - - parent, ok := checked[o] - times := 0 - - if ok { - times = counters[parent] - } else { - parent = o.Clone() - checked[o] = parent - } - - if times != MaxRepeat { - if tavor.DEBUG { - fmt.Printf("Clone (%p)%#v with parent (%p)%#v\n", t, t, parent, parent) - } - - c := parent.Clone() - - t.Set(c) - - counters[parent] = times + 1 - checked[c] = parent - - if iTok.parent != nil { - switch tt := iTok.parent.tok.(type) { - case token.ForwardToken: - tt.InternalReplace(t, c) - case lists.List: - tt.InternalReplace(t, c) - } - } else { - root = c - } - - queue.Unshift(&unrollToken{ - tok: c, - parent: iTok.parent, - }) - } else { - if tavor.DEBUG { - fmt.Printf("Reached max repeat of %d for (%p)%#v with parent (%p)%#v\n", MaxRepeat, t, t, parent, parent) - } - - t.Set(nil) - - ta := iTok.tok - tt := iTok.parent - - REMOVE: - for tt != nil { - switch l := tt.tok.(type) { - case token.ForwardToken: - if tavor.DEBUG { - fmt.Printf("Remove (%p)%#v from (%p)%#v\n", ta, ta, l, l) - } - - c := l.InternalLogicalRemove(ta) - - if c != nil { - break REMOVE - } - - ta = l - tt = tt.parent - case lists.List: - if tavor.DEBUG { - fmt.Printf("Remove (%p)%#v from (%p)%#v\n", ta, ta, l, l) - } - - c := l.InternalLogicalRemove(ta) - - if c != nil { - break REMOVE - } - - ta = l - tt = tt.parent - } - } - } - case token.ForwardToken: - if v := t.InternalGet(); v != nil { - queue.Push(&unrollToken{ - tok: v, - parent: iTok, - }) - } - case lists.List: - for i := 0; i < t.InternalLen(); i++ { - c, _ := t.InternalGet(i) - - queue.Push(&unrollToken{ - tok: c, - parent: iTok, - }) - } - } - } - - if tavor.DEBUG { - fmt.Println("Done unrolling") - } - - return root -} - func ParseTavor(src io.Reader) (token.Token, error) { p := &tavorParser{ earlyUse: make(map[string][]tokenUse), @@ -1300,7 +1163,7 @@ func ParseTavor(src io.Reader) (token.Token, error) { start := p.lookup["START"].token - start = p.unrollLoops(start) + start = tavor.UnrollPointers(start) return start, nil } diff --git a/parser/tavor_test.go b/parser/tavor_test.go index 57e7f1d..8d11a4b 100644 --- a/parser/tavor_test.go +++ b/parser/tavor_test.go @@ -7,6 +7,7 @@ import ( . "github.com/stretchr/testify/assert" + "github.com/zimmski/tavor" "github.com/zimmski/tavor/test" "github.com/zimmski/tavor/token" "github.com/zimmski/tavor/token/aggregates" @@ -403,7 +404,7 @@ func TestTavorParserAlternationsAndGroupings(t *testing.T) { Nil(t, err) Equal(t, tok, lists.NewAll( primitives.NewConstantInt(1), - lists.NewRepeat(primitives.NewConstantInt(2), 1, MaxRepeat), + lists.NewRepeat(primitives.NewConstantInt(2), 1, tavor.MaxRepeat), )) // or repeat @@ -414,7 +415,7 @@ func TestTavorParserAlternationsAndGroupings(t *testing.T) { lists.NewRepeat(lists.NewOne( primitives.NewConstantInt(2), primitives.NewConstantInt(3), - ), 1, MaxRepeat), + ), 1, tavor.MaxRepeat), primitives.NewConstantInt(4), )) @@ -423,7 +424,7 @@ func TestTavorParserAlternationsAndGroupings(t *testing.T) { Nil(t, err) Equal(t, tok, lists.NewAll( primitives.NewConstantInt(1), - lists.NewRepeat(primitives.NewConstantInt(2), 0, MaxRepeat), + lists.NewRepeat(primitives.NewConstantInt(2), 0, tavor.MaxRepeat), )) // or optional repeat @@ -434,7 +435,7 @@ func TestTavorParserAlternationsAndGroupings(t *testing.T) { lists.NewRepeat(lists.NewOne( primitives.NewConstantInt(2), primitives.NewConstantInt(3), - ), 0, MaxRepeat), + ), 0, tavor.MaxRepeat), primitives.NewConstantInt(4), )) @@ -443,7 +444,7 @@ func TestTavorParserAlternationsAndGroupings(t *testing.T) { Nil(t, err) Equal(t, tok, lists.NewAll( primitives.NewConstantInt(1), - lists.NewRepeat(primitives.NewConstantInt(2), 0, MaxRepeat), + lists.NewRepeat(primitives.NewConstantInt(2), 0, tavor.MaxRepeat), )) // exact repeat @@ -459,7 +460,7 @@ func TestTavorParserAlternationsAndGroupings(t *testing.T) { Nil(t, err) Equal(t, tok, lists.NewAll( primitives.NewConstantInt(1), - lists.NewRepeat(primitives.NewConstantInt(2), 3, MaxRepeat), + lists.NewRepeat(primitives.NewConstantInt(2), 3, tavor.MaxRepeat), )) // at most repeat @@ -499,7 +500,7 @@ func TestTavorParserTokenAttributes(t *testing.T) { primitives.NewConstantInt(1), primitives.NewConstantInt(2), primitives.NewConstantInt(3), - ), 0, MaxRepeat), + ), 0, tavor.MaxRepeat), primitives.NewConstantString("->"), aggregates.NewLen(list), )) diff --git a/tavor.go b/tavor.go index cb71efc..79ffc55 100644 --- a/tavor.go +++ b/tavor.go @@ -16,6 +16,10 @@ const ( Version = "0.1" ) +const ( + MaxRepeat = 2 +) + //TODO remove this var DEBUG = false @@ -101,3 +105,136 @@ func LoopExists(root token.Token) bool { return false } + +func UnrollPointers(root token.Token) token.Token { + type unrollToken struct { + tok token.Token + parent *unrollToken + } + + if DEBUG { + fmt.Println("Unroll pointers by cloning them") + } + + checked := make(map[token.Token]token.Token) + counters := make(map[token.Token]int) + + queue := linkedlist.New() + + queue.Push(&unrollToken{ + tok: root, + parent: nil, + }) + + for !queue.Empty() { + v, _ := queue.Shift() + iTok, _ := v.(*unrollToken) + + switch t := iTok.tok.(type) { + case *primitives.Pointer: + o := t.InternalGet() + + parent, ok := checked[o] + times := 0 + + if ok { + times = counters[parent] + } else { + parent = o.Clone() + checked[o] = parent + } + + if times != MaxRepeat { + if DEBUG { + fmt.Printf("Clone (%p)%#v with parent (%p)%#v\n", t, t, parent, parent) + } + + c := parent.Clone() + + t.Set(c) + + counters[parent] = times + 1 + checked[c] = parent + + if iTok.parent != nil { + switch tt := iTok.parent.tok.(type) { + case token.ForwardToken: + tt.InternalReplace(t, c) + case lists.List: + tt.InternalReplace(t, c) + } + } else { + root = c + } + + queue.Unshift(&unrollToken{ + tok: c, + parent: iTok.parent, + }) + } else { + if DEBUG { + fmt.Printf("Reached max repeat of %d for (%p)%#v with parent (%p)%#v\n", MaxRepeat, t, t, parent, parent) + } + + t.Set(nil) + + ta := iTok.tok + tt := iTok.parent + + REMOVE: + for tt != nil { + switch l := tt.tok.(type) { + case token.ForwardToken: + if DEBUG { + fmt.Printf("Remove (%p)%#v from (%p)%#v\n", ta, ta, l, l) + } + + c := l.InternalLogicalRemove(ta) + + if c != nil { + break REMOVE + } + + ta = l + tt = tt.parent + case lists.List: + if DEBUG { + fmt.Printf("Remove (%p)%#v from (%p)%#v\n", ta, ta, l, l) + } + + c := l.InternalLogicalRemove(ta) + + if c != nil { + break REMOVE + } + + ta = l + tt = tt.parent + } + } + } + case token.ForwardToken: + if v := t.InternalGet(); v != nil { + queue.Push(&unrollToken{ + tok: v, + parent: iTok, + }) + } + case lists.List: + for i := 0; i < t.InternalLen(); i++ { + c, _ := t.InternalGet(i) + + queue.Push(&unrollToken{ + tok: c, + parent: iTok, + }) + } + } + } + + if DEBUG { + fmt.Println("Done unrolling") + } + + return root +}