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) 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) nodeName() string { return p.name }
|
||||||
func (p *choiceParser) nodeID() int { return p.id }
|
func (p *choiceParser) nodeID() int { return p.id }
|
||||||
func (p *choiceParser) commitType() CommitType { return p.commit }
|
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)
|
c.results.markPending(c.offset, p.id)
|
||||||
|
|
||||||
|
var (
|
||||||
|
match bool
|
||||||
|
optionIndex int
|
||||||
|
foundMatch bool
|
||||||
|
failingParser parser
|
||||||
|
)
|
||||||
|
|
||||||
from := c.offset
|
from := c.offset
|
||||||
to := c.offset
|
to := c.offset
|
||||||
|
|
||||||
var match bool
|
|
||||||
var optionIndex int
|
|
||||||
var foundMatch bool
|
|
||||||
|
|
||||||
initialFailOffset := c.failOffset
|
initialFailOffset := c.failOffset
|
||||||
initialFailingParser := c.failingParser
|
initialFailingParser := c.failingParser
|
||||||
failOffset := initialFailOffset
|
failOffset := initialFailOffset
|
||||||
var failingParser parser
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
foundMatch = false
|
foundMatch = false
|
||||||
@ -288,3 +272,21 @@ func (b *choiceBuilder) build(c *context) ([]*Node, bool) {
|
|||||||
tokens: c.tokens,
|
tokens: c.tokens,
|
||||||
}}, true
|
}}, 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)
|
||||||
|
}
|
||||||
|
17
context.go
17
context.go
@ -136,25 +136,18 @@ func (c *context) finalizeParse(root parser) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
to, match, found := c.results.longestResult(0, root.nodeID())
|
to, match, found := c.results.longestResult(0, root.nodeID())
|
||||||
|
if !found || !match || found && match && to < c.readOffset {
|
||||||
if found && match && to < c.readOffset {
|
|
||||||
return c.parseError(p)
|
return c.parseError(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !found || !match {
|
|
||||||
return c.parseError(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !c.eof {
|
|
||||||
c.read()
|
c.read()
|
||||||
if !c.eof {
|
if c.eof {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
if c.readErr != nil {
|
if c.readErr != nil {
|
||||||
return c.readErr
|
return c.readErr
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.parseError(root)
|
return c.parseError(root)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
@ -13,12 +13,6 @@ type errorTestItem struct {
|
|||||||
perr ParseError
|
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) {
|
func testParseErrorItem(s *Syntax, test errorTestItem) func(t *testing.T) {
|
||||||
return func(t *testing.T) {
|
return func(t *testing.T) {
|
||||||
_, err := s.Parse(bytes.NewBufferString(test.doc))
|
_, err := s.Parse(bytes.NewBufferString(test.doc))
|
||||||
@ -32,9 +26,8 @@ func testParseErrorItem(s *Syntax, test errorTestItem) func(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
perr.Input = ""
|
perr.Input = ""
|
||||||
perr.registry = nil
|
|
||||||
|
|
||||||
if !checkParseError(*perr, test.perr) {
|
if !reflect.DeepEqual(*perr, test.perr) {
|
||||||
t.Error("invalid error returned")
|
t.Error("invalid error returned")
|
||||||
t.Log("got: ", *perr)
|
t.Log("got: ", *perr)
|
||||||
t.Log("expected:", test.perr)
|
t.Log("expected:", test.perr)
|
||||||
|
64
results.go
64
results.go
@ -6,24 +6,44 @@ type results struct {
|
|||||||
isPending [][]int
|
isPending [][]int
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *results) ensureOffset(offset int) {
|
func ensureOffsetInts(ints [][]int, offset int) [][]int {
|
||||||
if len(r.match) > offset {
|
if len(ints) > offset {
|
||||||
return
|
return ints
|
||||||
}
|
}
|
||||||
|
|
||||||
if cap(r.match) > offset {
|
if cap(ints) > offset {
|
||||||
r.match = r.match[:offset+1]
|
ints = ints[:offset+1]
|
||||||
return
|
return ints
|
||||||
}
|
}
|
||||||
|
|
||||||
r.match = r.match[:cap(r.match)]
|
ints = ints[:cap(ints)]
|
||||||
for i := len(r.match); i <= offset; i++ {
|
for i := len(ints); i <= offset; i++ {
|
||||||
r.match = append(r.match, nil)
|
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) {
|
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 {
|
for i := 0; i < len(r.match[offset]); i += 2 {
|
||||||
if r.match[offset][i] != id || r.match[offset][i+1] != to {
|
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 {
|
r.noMatch = ensureOffsetIDs(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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if r.noMatch[offset] == nil {
|
if r.noMatch[offset] == nil {
|
||||||
r.noMatch[offset] = &idSet{}
|
r.noMatch[offset] = &idSet{}
|
||||||
}
|
}
|
||||||
@ -146,17 +156,7 @@ func (r *results) pending(offset, id int) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (r *results) markPending(offset, id int) {
|
func (r *results) markPending(offset, id int) {
|
||||||
if len(r.isPending) <= id {
|
r.isPending = ensureOffsetInts(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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := range r.isPending[id] {
|
for i := range r.isPending[id] {
|
||||||
if r.isPending[id][i] == -1 {
|
if r.isPending[id][i] == -1 {
|
||||||
r.isPending[id][i] = offset
|
r.isPending[id][i] = offset
|
||||||
|
19
sequence.go
19
sequence.go
@ -196,16 +196,24 @@ func (p *sequenceParser) parse(c *context) {
|
|||||||
c.results.markPending(c.offset, p.id)
|
c.results.markPending(c.offset, p.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
currentCount int
|
||||||
|
parsed bool
|
||||||
|
)
|
||||||
|
|
||||||
itemIndex := 0
|
itemIndex := 0
|
||||||
var currentCount int
|
|
||||||
from := c.offset
|
from := c.offset
|
||||||
to := c.offset
|
to := c.offset
|
||||||
var parsed bool
|
|
||||||
|
|
||||||
for itemIndex < len(p.items) {
|
for itemIndex < len(p.items) {
|
||||||
p.items[itemIndex].parse(c)
|
p.items[itemIndex].parse(c)
|
||||||
if !c.matchLast {
|
if !c.matchLast {
|
||||||
if currentCount < p.ranges[itemIndex][0] {
|
if currentCount >= p.ranges[itemIndex][0] {
|
||||||
|
itemIndex++
|
||||||
|
currentCount = 0
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
if c.failingParser == nil &&
|
if c.failingParser == nil &&
|
||||||
p.commitType()&userDefined != 0 &&
|
p.commitType()&userDefined != 0 &&
|
||||||
p.commitType()&Whitespace == 0 &&
|
p.commitType()&Whitespace == 0 &&
|
||||||
@ -221,11 +229,6 @@ func (p *sequenceParser) parse(c *context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
itemIndex++
|
|
||||||
currentCount = 0
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
parsed = c.offset > to
|
parsed = c.offset > to
|
||||||
if parsed {
|
if parsed {
|
||||||
currentCount++
|
currentCount++
|
||||||
|
@ -61,8 +61,6 @@ type ParseError struct {
|
|||||||
|
|
||||||
// Definition tells the right-most unmatched parser definition.
|
// Definition tells the right-most unmatched parser definition.
|
||||||
Definition string
|
Definition string
|
||||||
|
|
||||||
registry *registry
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Syntax struct {
|
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 err := c.finalizeParse(s.parser); err != nil {
|
||||||
if perr, ok := err.(*ParseError); ok {
|
if perr, ok := err.(*ParseError); ok {
|
||||||
perr.Input = "<input>"
|
perr.Input = "<input>"
|
||||||
perr.registry = s.registry
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil, err
|
return nil, err
|
||||||
|
Loading…
Reference in New Issue
Block a user