Skip to content

Commit

Permalink
feat: add StripSource to Scanner (#68)
Browse files Browse the repository at this point in the history
- Add StripSource to Scanner

- Use pure string instead of string address since origin string is changed during parsing time
  • Loading branch information
ChloePlanet authored Apr 15, 2020
1 parent d5b0d9d commit 63ecbfa
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 26 deletions.
27 changes: 13 additions & 14 deletions ast/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,17 +70,17 @@ 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
}
}
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
}
Expand Down Expand Up @@ -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
Expand All @@ -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()
}
}
Expand All @@ -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
}
Expand Down
36 changes: 24 additions & 12 deletions parser/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit 63ecbfa

Please sign in to comment.