From 63ecbfa03b8997fd6e4690ba87860d4ac3838817 Mon Sep 17 00:00:00 2001 From: Chloe Date: Wed, 15 Apr 2020 11:23:41 +1000 Subject: [PATCH] feat: add StripSource to Scanner (#68) - Add StripSource to Scanner - Use pure string instead of string address since origin string is changed during parsing time --- ast/node.go | 27 +++++++++++++-------------- parser/scanner.go | 36 ++++++++++++++++++++++++------------ 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/ast/node.go b/ast/node.go index 16ec14e..4237f71 100644 --- a/ast/node.go +++ b/ast/node.go @@ -70,8 +70,8 @@ func (l Leaf) collapse(level int) Node { type Branch map[string]Children -func (n Branch) One(name string) Node { - if c, has := n[name]; has { +func (b Branch) One(name string) Node { + if c, has := b[name]; has { if one, ok := c.(One); ok { return one.Node } @@ -79,8 +79,8 @@ func (n Branch) One(name string) Node { return nil } -func (n Branch) Many(name string) []Node { - if c, has := n[name]; has { +func (b Branch) Many(name string) []Node { + if c, has := b[name]; has { if many, ok := c.(Many); ok { return many } @@ -138,9 +138,9 @@ func (l Leaf) clone() Node { return l } -func (n Branch) clone() Node { +func (b Branch) clone() Node { result := Branch{} - for name, node := range n { + for name, node := range b { result[name] = node.clone() } return result @@ -162,12 +162,12 @@ func (l Leaf) narrow() bool { return true } -func (n Branch) narrow() bool { - switch len(n) { +func (b Branch) narrow() bool { + switch len(b) { case 0: return true case 1: - for _, group := range n { + for _, group := range b { return group.narrow() } } @@ -193,18 +193,17 @@ func (b Branch) ContentEquals(other Node) bool { return false } for k, v := range b { - switch v.(type) { + switch v := v.(type) { case One: - if !v.(One).Node.ContentEquals(other.One(k)) { + if !v.Node.ContentEquals(other.One(k)) { return false } case Many: - nodes := v.(Many) otherNodes := other.Many(k) - if len(nodes) != len(otherNodes) { + if len(v) != len(otherNodes) { return false } - for i, n := range nodes { + for i, n := range v { if !n.ContentEquals(otherNodes[i]) { return false } diff --git a/parser/scanner.go b/parser/scanner.go index 17c3699..2bedd8a 100644 --- a/parser/scanner.go +++ b/parser/scanner.go @@ -8,38 +8,41 @@ import ( type Scanner struct { src source // the source the scanner is drawing from - sliceStart int // the start of the slice visible to the scanner - sliceLength int // the length of the slice visible to the scanner + sliceStart int // the start of the slice visible to the scanner, based on the original src + sliceLength int // the length of the slice visible to the scanner, based on the original src } type source interface { length() int // the length of the entire source string slice(i, length int) string // the string of the given slice filename() string // the name of the file from which the source is derived (or empty if none) + stripSource(i, length int) source } type stringSource struct { - origin *string // the entire source string - f string // the source filename + origin string // the entire source string + f string // the source filename } func NewScanner(str string) *Scanner { - return &Scanner{stringSource{origin: &str}, 0, len(str)} + return &Scanner{stringSource{origin: str}, 0, len(str)} } func NewScannerWithFilename(str, filename string) *Scanner { - return &Scanner{stringSource{&str, filename}, 0, len(str)} + return &Scanner{stringSource{str, filename}, 0, len(str)} } func NewScannerAt(str string, offset, size int) *Scanner { - if offset+size > len(str) { - panic(fmt.Errorf("%d is out of range [:%d]", offset+size, len(str))) - } - return &Scanner{stringSource{origin: &str}, offset, size} + return &Scanner{stringSource{origin: str}, offset, size} } // - Scanner +func (r Scanner) StripSource() Scanner { + r.src = r.src.stripSource(r.sliceStart, r.sliceLength) + return r +} + // The name of the file from which the source is derived (or empty if none). func (s Scanner) Filename() string { return s.src.filename() @@ -162,12 +165,21 @@ func (s *Scanner) EatRegexp(re *regexp.Regexp, match *Scanner, captures []Scanne // - stringSource +func (s stringSource) stripSource(offset, size int) source { + s.origin = s.slice(offset, size) + return s +} + func (s stringSource) length() int { - return len(*s.origin) + return len(s.origin) } func (s stringSource) slice(i, length int) string { - return (*s.origin)[i : i+length] + // Since offset and length based on the original origin string, so they might be out of range + if i < 0 || i+length < 0 || i > len(s.origin) || i+length > len(s.origin) { + return s.origin + } + return (s.origin)[i : i+length] } func (s stringSource) filename() string {