refactor parsing phase
This commit is contained in:
parent
c4591babe0
commit
6d3fe17ddb
50
choice.go
50
choice.go
@ -131,24 +131,6 @@ func (d *choiceDefinition) parser() parser {
|
||||
|
||||
func (d *choiceDefinition) builder() builder { return d.cbuilder }
|
||||
|
||||
func (d *choiceDefinition) format(r *registry, f formatFlags) string {
|
||||
var chars []rune
|
||||
for i := range d.options {
|
||||
if i > 0 {
|
||||
chars = append(chars, []rune(" | ")...)
|
||||
}
|
||||
|
||||
optionDef, _ := r.definition(d.options[i])
|
||||
if optionDef.commitType()&userDefined != 0 {
|
||||
chars = append(chars, []rune(optionDef.nodeName())...)
|
||||
} else {
|
||||
chars = append(chars, []rune(optionDef.format(r, f))...)
|
||||
}
|
||||
}
|
||||
|
||||
return string(chars)
|
||||
}
|
||||
|
||||
func (p *choiceParser) nodeName() string { return p.name }
|
||||
func (p *choiceParser) nodeID() int { return p.id }
|
||||
func (p *choiceParser) commitType() CommitType { return p.commit }
|
||||
@ -164,17 +146,19 @@ func (p *choiceParser) parse(c *context) {
|
||||
}
|
||||
|
||||
c.results.markPending(c.offset, p.id)
|
||||
|
||||
var (
|
||||
match bool
|
||||
optionIndex int
|
||||
foundMatch bool
|
||||
failingParser parser
|
||||
)
|
||||
|
||||
from := c.offset
|
||||
to := c.offset
|
||||
|
||||
var match bool
|
||||
var optionIndex int
|
||||
var foundMatch bool
|
||||
|
||||
initialFailOffset := c.failOffset
|
||||
initialFailingParser := c.failingParser
|
||||
failOffset := initialFailOffset
|
||||
var failingParser parser
|
||||
|
||||
for {
|
||||
foundMatch = false
|
||||
@ -288,3 +272,21 @@ func (b *choiceBuilder) build(c *context) ([]*Node, bool) {
|
||||
tokens: c.tokens,
|
||||
}}, true
|
||||
}
|
||||
|
||||
func (d *choiceDefinition) format(r *registry, f formatFlags) string {
|
||||
var chars []rune
|
||||
for i := range d.options {
|
||||
if i > 0 {
|
||||
chars = append(chars, []rune(" | ")...)
|
||||
}
|
||||
|
||||
optionDef, _ := r.definition(d.options[i])
|
||||
if optionDef.commitType()&userDefined != 0 {
|
||||
chars = append(chars, []rune(optionDef.nodeName())...)
|
||||
} else {
|
||||
chars = append(chars, []rune(optionDef.format(r, f))...)
|
||||
}
|
||||
}
|
||||
|
||||
return string(chars)
|
||||
}
|
||||
|
21
context.go
21
context.go
@ -136,25 +136,18 @@ func (c *context) finalizeParse(root parser) error {
|
||||
}
|
||||
|
||||
to, match, found := c.results.longestResult(0, root.nodeID())
|
||||
|
||||
if found && match && to < c.readOffset {
|
||||
if !found || !match || found && match && to < c.readOffset {
|
||||
return c.parseError(p)
|
||||
}
|
||||
|
||||
if !found || !match {
|
||||
return c.parseError(p)
|
||||
c.read()
|
||||
if c.eof {
|
||||
return nil
|
||||
}
|
||||
|
||||
if !c.eof {
|
||||
c.read()
|
||||
if !c.eof {
|
||||
if c.readErr != nil {
|
||||
return c.readErr
|
||||
}
|
||||
|
||||
return c.parseError(root)
|
||||
}
|
||||
if c.readErr != nil {
|
||||
return c.readErr
|
||||
}
|
||||
|
||||
return nil
|
||||
return c.parseError(root)
|
||||
}
|
||||
|
@ -13,12 +13,6 @@ type errorTestItem struct {
|
||||
perr ParseError
|
||||
}
|
||||
|
||||
func checkParseError(left, right ParseError) bool {
|
||||
left.registry = nil
|
||||
right.registry = nil
|
||||
return reflect.DeepEqual(left, right)
|
||||
}
|
||||
|
||||
func testParseErrorItem(s *Syntax, test errorTestItem) func(t *testing.T) {
|
||||
return func(t *testing.T) {
|
||||
_, err := s.Parse(bytes.NewBufferString(test.doc))
|
||||
@ -32,9 +26,8 @@ func testParseErrorItem(s *Syntax, test errorTestItem) func(t *testing.T) {
|
||||
}
|
||||
|
||||
perr.Input = ""
|
||||
perr.registry = nil
|
||||
|
||||
if !checkParseError(*perr, test.perr) {
|
||||
if !reflect.DeepEqual(*perr, test.perr) {
|
||||
t.Error("invalid error returned")
|
||||
t.Log("got: ", *perr)
|
||||
t.Log("expected:", test.perr)
|
||||
|
64
results.go
64
results.go
@ -6,24 +6,44 @@ type results struct {
|
||||
isPending [][]int
|
||||
}
|
||||
|
||||
func (r *results) ensureOffset(offset int) {
|
||||
if len(r.match) > offset {
|
||||
return
|
||||
func ensureOffsetInts(ints [][]int, offset int) [][]int {
|
||||
if len(ints) > offset {
|
||||
return ints
|
||||
}
|
||||
|
||||
if cap(r.match) > offset {
|
||||
r.match = r.match[:offset+1]
|
||||
return
|
||||
if cap(ints) > offset {
|
||||
ints = ints[:offset+1]
|
||||
return ints
|
||||
}
|
||||
|
||||
r.match = r.match[:cap(r.match)]
|
||||
for i := len(r.match); i <= offset; i++ {
|
||||
r.match = append(r.match, nil)
|
||||
ints = ints[:cap(ints)]
|
||||
for i := len(ints); i <= offset; i++ {
|
||||
ints = append(ints, nil)
|
||||
}
|
||||
|
||||
return ints
|
||||
}
|
||||
|
||||
func ensureOffsetIDs(ids []*idSet, offset int) []*idSet {
|
||||
if len(ids) > offset {
|
||||
return ids
|
||||
}
|
||||
|
||||
if cap(ids) > offset {
|
||||
ids = ids[:offset+1]
|
||||
return ids
|
||||
}
|
||||
|
||||
ids = ids[:cap(ids)]
|
||||
for i := len(ids); i <= offset; i++ {
|
||||
ids = append(ids, nil)
|
||||
}
|
||||
|
||||
return ids
|
||||
}
|
||||
|
||||
func (r *results) setMatch(offset, id, to int) {
|
||||
r.ensureOffset(offset)
|
||||
r.match = ensureOffsetInts(r.match, offset)
|
||||
|
||||
for i := 0; i < len(r.match[offset]); i += 2 {
|
||||
if r.match[offset][i] != id || r.match[offset][i+1] != to {
|
||||
@ -47,17 +67,7 @@ func (r *results) setNoMatch(offset, id int) {
|
||||
}
|
||||
}
|
||||
|
||||
if len(r.noMatch) <= offset {
|
||||
if cap(r.noMatch) > offset {
|
||||
r.noMatch = r.noMatch[:offset+1]
|
||||
} else {
|
||||
r.noMatch = r.noMatch[:cap(r.noMatch)]
|
||||
for i := cap(r.noMatch); i <= offset; i++ {
|
||||
r.noMatch = append(r.noMatch, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r.noMatch = ensureOffsetIDs(r.noMatch, offset)
|
||||
if r.noMatch[offset] == nil {
|
||||
r.noMatch[offset] = &idSet{}
|
||||
}
|
||||
@ -146,17 +156,7 @@ func (r *results) pending(offset, id int) bool {
|
||||
}
|
||||
|
||||
func (r *results) markPending(offset, id int) {
|
||||
if len(r.isPending) <= id {
|
||||
if cap(r.isPending) > id {
|
||||
r.isPending = r.isPending[:id+1]
|
||||
} else {
|
||||
r.isPending = r.isPending[:cap(r.isPending)]
|
||||
for i := cap(r.isPending); i <= id; i++ {
|
||||
r.isPending = append(r.isPending, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r.isPending = ensureOffsetInts(r.isPending, id)
|
||||
for i := range r.isPending[id] {
|
||||
if r.isPending[id][i] == -1 {
|
||||
r.isPending[id][i] = offset
|
||||
|
41
sequence.go
41
sequence.go
@ -196,34 +196,37 @@ func (p *sequenceParser) parse(c *context) {
|
||||
c.results.markPending(c.offset, p.id)
|
||||
}
|
||||
|
||||
var (
|
||||
currentCount int
|
||||
parsed bool
|
||||
)
|
||||
|
||||
itemIndex := 0
|
||||
var currentCount int
|
||||
from := c.offset
|
||||
to := c.offset
|
||||
var parsed bool
|
||||
|
||||
for itemIndex < len(p.items) {
|
||||
p.items[itemIndex].parse(c)
|
||||
if !c.matchLast {
|
||||
if currentCount < p.ranges[itemIndex][0] {
|
||||
if c.failingParser == nil &&
|
||||
p.commitType()&userDefined != 0 &&
|
||||
p.commitType()&Whitespace == 0 &&
|
||||
p.commitType()&FailPass == 0 {
|
||||
c.failingParser = p
|
||||
}
|
||||
|
||||
c.fail(from)
|
||||
if !p.allChars {
|
||||
c.results.unmarkPending(from, p.id)
|
||||
}
|
||||
|
||||
return
|
||||
if currentCount >= p.ranges[itemIndex][0] {
|
||||
itemIndex++
|
||||
currentCount = 0
|
||||
continue
|
||||
}
|
||||
|
||||
itemIndex++
|
||||
currentCount = 0
|
||||
continue
|
||||
if c.failingParser == nil &&
|
||||
p.commitType()&userDefined != 0 &&
|
||||
p.commitType()&Whitespace == 0 &&
|
||||
p.commitType()&FailPass == 0 {
|
||||
c.failingParser = p
|
||||
}
|
||||
|
||||
c.fail(from)
|
||||
if !p.allChars {
|
||||
c.results.unmarkPending(from, p.id)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
parsed = c.offset > to
|
||||
|
@ -61,8 +61,6 @@ type ParseError struct {
|
||||
|
||||
// Definition tells the right-most unmatched parser definition.
|
||||
Definition string
|
||||
|
||||
registry *registry
|
||||
}
|
||||
|
||||
type Syntax struct {
|
||||
@ -442,7 +440,6 @@ func (s *Syntax) Parse(r io.Reader) (*Node, error) {
|
||||
if err := c.finalizeParse(s.parser); err != nil {
|
||||
if perr, ok := err.(*ParseError); ok {
|
||||
perr.Input = "<input>"
|
||||
perr.registry = s.registry
|
||||
}
|
||||
|
||||
return nil, err
|
||||
|
Loading…
Reference in New Issue
Block a user