fix/ignore-pending-builders

This commit is contained in:
Arpad Ryszka 2018-08-19 22:40:01 +02:00
parent 3df7e79a0e
commit dbe4a5302b
9 changed files with 194 additions and 75 deletions

View File

@ -9,10 +9,11 @@ type choiceParser struct {
}
type choiceBuilder struct {
name string
id int
commit CommitType
options []builder
name string
id int
commit CommitType
options []builder
generalizations []int
}
func (p *choiceParser) nodeName() string { return p.name }
@ -123,12 +124,18 @@ func (b *choiceBuilder) build(c *context) ([]*Node, bool) {
if parsed {
c.results.dropMatchTo(c.offset, b.id, to)
for _, g := range b.generalizations {
c.results.dropMatchTo(c.offset, g, to)
}
} else {
if c.results.pending(c.offset, b.id) {
return nil, false
}
c.results.markPending(c.offset, b.id)
for _, g := range b.generalizations {
c.results.markPending(c.offset, g)
}
}
var option builder
@ -142,6 +149,9 @@ func (b *choiceBuilder) build(c *context) ([]*Node, bool) {
n, _ := option.build(c)
if !parsed {
c.results.unmarkPending(from, b.id)
for _, g := range b.generalizations {
c.results.unmarkPending(from, g)
}
}
if b.commit&Alias != 0 {

View File

@ -54,20 +54,11 @@ func (d *choiceDefinition) validate(r *registry) error {
return nil
}
func (d *choiceDefinition) createBuilder() {
d.cbuilder = &choiceBuilder{
name: d.name,
id: d.id,
commit: d.commit,
}
}
func (d *choiceDefinition) initOptions(r *registry) {
for _, o := range d.options {
def := r.definition[o]
d.optionDefs = append(d.optionDefs, def)
def.init(r)
d.cbuilder.options = append(d.cbuilder.options, def.builder())
def.addGeneralization(d.id)
}
}
@ -78,7 +69,6 @@ func (d *choiceDefinition) init(r *registry) {
}
d.initialized = true
d.createBuilder()
d.initOptions(r)
}
@ -119,7 +109,30 @@ func (d *choiceDefinition) parser() parser {
return d.cparser
}
func (d *choiceDefinition) builder() builder { return d.cbuilder }
func (d *choiceDefinition) createBuilder() {
d.cbuilder = &choiceBuilder{
name: d.name,
id: d.id,
commit: d.commit,
generalizations: d.generalizations,
}
}
func (d *choiceDefinition) createOptionBuilders() {
for _, def := range d.optionDefs {
option := def.builder()
d.cbuilder.options = append(d.cbuilder.options, option)
}
}
func (d *choiceDefinition) builder() builder {
if d.cbuilder != nil {
return d.cbuilder
}
d.createBuilder()
d.createOptionBuilders()
return d.cbuilder
}
func (d *choiceDefinition) format(r *registry, f formatFlags) string {
var chars []rune

View File

@ -186,19 +186,16 @@ select = "select" nl* "{" sep?
go = "go" nl* function-application;
defer = "defer" nl* function-application;
break = "break";
continue = "continue";
range-over-expression = symbol nl* "in" nl* (expression | range) | range;
loop-expression:alias = expression | range-over-expression;
loop = "for" ((nl* loop-expression)? nl* block | nl* block);
assignable:alias = symbol-indexer | simple-indexer | symbol;
assign-capture = assignable (nl* "=")? nl* expression;
assign-capture:alias = primary-expression (nl* "=")? nl* expression;
assign-capture-list:alias = assign-capture (list-sep assign-capture)*;
assign-set:alias = "set" nl* assign-capture;
assign-equal:alias = assignable nl* "=" nl* expression;
assign-group:alias = "set" nl* "(" list-sep? assign-capture-list? list-sep? ")";
assignment = assign-set | assign-equal | assign-group;
assign-eq:alias = primary-expression nl* "=" nl* expression;
assign-group:alias = "set" nl* "(" (list-sep assign-capture-list)? list-sep? ")";
assignment = assign-set | assign-eq | assign-group;
value-capture-fact:alias = symbol (nl* "=")? nl* expression;
value-capture = value-capture-fact;
@ -254,8 +251,6 @@ statement:alias = simple-statement
| if
| switch
| select
| break
| continue
| loop
| definition
| require

File diff suppressed because one or more lines are too long

View File

@ -2118,12 +2118,9 @@ func TestMML(t *testing.T) {
nodes: []*Node{{
Name: "assignment",
Nodes: []*Node{{
Name: "assign-capture",
Nodes: []*Node{{
Name: "symbol",
}, {
Name: "symbol",
}},
Name: "symbol",
}, {
Name: "symbol",
}},
}},
ignorePosition: true,
@ -2133,37 +2130,96 @@ func TestMML(t *testing.T) {
nodes: []*Node{{
Name: "assignment",
Nodes: []*Node{{
Name: "assign-capture",
Nodes: []*Node{{
Name: "symbol",
}, {
Name: "symbol",
}},
Name: "symbol",
}, {
Name: "symbol",
}},
}},
ignorePosition: true,
}, {
title: "assign, group",
text: `set (
a = b
c d
)`,
a = b
c d
)`,
nodes: []*Node{{
Name: "assignment",
Nodes: []*Node{{
Name: "assign-capture",
Name: "symbol",
}, {
Name: "symbol",
}, {
Name: "symbol",
}, {
Name: "symbol",
}},
}},
ignorePosition: true,
}, {
title: "assign to struct field",
text: "set a.b c",
nodes: []*Node{{
Name: "assignment",
Nodes: []*Node{{
Name: "symbol-indexer",
Nodes: []*Node{{
Name: "symbol",
}, {
Name: "symbol",
}},
}, {
Name: "assign-capture",
Name: "symbol",
}},
}},
ignorePosition: true,
}, {
title: "indexer",
text: "set a[1] 42",
nodes: []*Node{{
Name: "assignment",
Nodes: []*Node{{
Name: "expression-indexer",
Nodes: []*Node{{
Name: "symbol",
}, {
Name: "symbol",
Name: "int",
}},
}, {
Name: "int",
}},
}},
ignorePosition: true,
}, {
title: "indexer, eq",
text: "a[1] = 42",
nodes: []*Node{{
Name: "assignment",
Nodes: []*Node{{
Name: "expression-indexer",
Nodes: []*Node{{
Name: "symbol",
}, {
Name: "int",
}},
}, {
Name: "int",
}},
}},
ignorePosition: true,
}, {
title: "indexer, set, eq",
text: "set a[1] = 42",
nodes: []*Node{{
Name: "assignment",
Nodes: []*Node{{
Name: "expression-indexer",
Nodes: []*Node{{
Name: "symbol",
}, {
Name: "int",
}},
}, {
Name: "int",
}},
}},
ignorePosition: true,

View File

@ -2669,9 +2669,9 @@ func TestMMLExp(t *testing.T) {
}, {
title: "assign, group",
text: `set (
a = b
c d
)`,
a = b
c d
)`,
nodes: []*Node{{
Name: "assignment",
Nodes: []*Node{{

View File

@ -96,12 +96,13 @@ type sequenceParser struct {
allChars bool
}
type sequenceBuilder struct {
name string
id int
commit CommitType
items []builder
ranges [][]int
allChars bool
name string
id int
commit CommitType
items []builder
ranges [][]int
generalizations []int
allChars bool
}
func (p *sequenceParser) nodeName() string {
@ -191,11 +192,17 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) {
return []*Node{{Name: b.name, From: from, To: to, tokens: c.tokens}}, true
} else if parsed {
c.results.dropMatchTo(c.offset, b.id, to)
for _, g := range b.generalizations {
c.results.dropMatchTo(c.offset, g, to)
}
} else {
if c.results.pending(c.offset, b.id) {
return nil, false
}
c.results.markPending(c.offset, b.id)
for _, g := range b.generalizations {
c.results.markPending(c.offset, g)
}
}
var (
itemIndex int
@ -229,6 +236,9 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) {
}
if !parsed {
c.results.unmarkPending(from, b.id)
for _, g := range b.generalizations {
c.results.unmarkPending(from, g)
}
}
if b.commit&Alias != 0 {
return nodes, true
@ -244,10 +254,11 @@ type choiceParser struct {
generalizations []int
}
type choiceBuilder struct {
name string
id int
commit CommitType
options []builder
name string
id int
commit CommitType
options []builder
generalizations []int
}
func (p *choiceParser) nodeName() string {
@ -346,11 +357,17 @@ func (b *choiceBuilder) build(c *context) ([]*Node, bool) {
parsed := to > from
if parsed {
c.results.dropMatchTo(c.offset, b.id, to)
for _, g := range b.generalizations {
c.results.dropMatchTo(c.offset, g, to)
}
} else {
if c.results.pending(c.offset, b.id) {
return nil, false
}
c.results.markPending(c.offset, b.id)
for _, g := range b.generalizations {
c.results.markPending(c.offset, g)
}
}
var option builder
for _, o := range b.options {
@ -362,6 +379,9 @@ func (b *choiceBuilder) build(c *context) ([]*Node, bool) {
n, _ := option.build(c)
if !parsed {
c.results.unmarkPending(from, b.id)
for _, g := range b.generalizations {
c.results.unmarkPending(from, g)
}
}
if b.commit&Alias != 0 {
return n, true

View File

@ -11,12 +11,13 @@ type sequenceParser struct {
}
type sequenceBuilder struct {
name string
id int
commit CommitType
items []builder
ranges [][]int
allChars bool
name string
id int
commit CommitType
items []builder
ranges [][]int
generalizations []int
allChars bool
}
func (p *sequenceParser) nodeName() string { return p.name }
@ -123,12 +124,19 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) {
}}, true
} else if parsed {
c.results.dropMatchTo(c.offset, b.id, to)
for _, g := range b.generalizations {
c.results.dropMatchTo(c.offset, g, to)
}
} else {
if c.results.pending(c.offset, b.id) {
return nil, false
}
c.results.markPending(c.offset, b.id)
for _, g := range b.generalizations {
c.results.markPending(c.offset, g)
}
}
var (
@ -170,6 +178,9 @@ func (b *sequenceBuilder) build(c *context) ([]*Node, bool) {
if !parsed {
c.results.unmarkPending(from, b.id)
for _, g := range b.generalizations {
c.results.unmarkPending(from, g)
}
}
if b.commit&Alias != 0 {

View File

@ -92,22 +92,12 @@ func (d *sequenceDefinition) validate(r *registry) error {
return nil
}
func (d *sequenceDefinition) createBuilder() {
d.sbuilder = &sequenceBuilder{
name: d.name,
id: d.id,
commit: d.commit,
ranges: d.ranges,
}
}
func (d *sequenceDefinition) initItems(r *registry) {
allChars := true
for _, item := range d.items {
def := r.definition[item.Name]
d.itemDefs = append(d.itemDefs, def)
def.init(r)
d.sbuilder.items = append(d.sbuilder.items, def.builder())
if allChars {
if _, isChar := def.(*charParser); !isChar {
allChars = false
@ -115,7 +105,6 @@ func (d *sequenceDefinition) initItems(r *registry) {
}
}
d.sbuilder.allChars = allChars
d.allChars = allChars
}
@ -126,7 +115,6 @@ func (d *sequenceDefinition) init(r *registry) {
d.initialized = true
d.initRanges()
d.createBuilder()
d.initItems(r)
}
@ -166,7 +154,33 @@ func (d *sequenceDefinition) parser() parser {
return d.sparser
}
func (d *sequenceDefinition) builder() builder { return d.sbuilder }
func (d *sequenceDefinition) createBuilder() {
d.sbuilder = &sequenceBuilder{
name: d.name,
id: d.id,
commit: d.commit,
ranges: d.ranges,
allChars: d.allChars,
generalizations: d.generalizations,
}
}
func (d *sequenceDefinition) createItemBuilders() {
for _, item := range d.itemDefs {
pi := item.builder()
d.sbuilder.items = append(d.sbuilder.items, pi)
}
}
func (d *sequenceDefinition) builder() builder {
if d.sbuilder != nil {
return d.sbuilder
}
d.createBuilder()
d.createItemBuilders()
return d.sbuilder
}
func (d *sequenceDefinition) isCharSequence(r *registry) bool {
for i := range d.originalItems {