|
@@ -9,15 +9,15 @@ import . "src.eruta.nl/beoran/ll1/flexer"
|
|
|
|
|
|
// A TokenMapper maps a token to a Species.
|
|
// A TokenMapper maps a token to a Species.
|
|
type TokenMapper interface {
|
|
type TokenMapper interface {
|
|
- // Returns the pecies to use for the token. If nil, the token
|
|
|
|
|
|
+ // Returns the species to use for the grammar rule. If nil, the token
|
|
// may be skipped.
|
|
// may be skipped.
|
|
- Map(t Token) Species
|
|
|
|
|
|
+ Map(t Rule) Species
|
|
}
|
|
}
|
|
|
|
|
|
type DefaultMapper struct{}
|
|
type DefaultMapper struct{}
|
|
|
|
|
|
-func (DefaultMapper) Map(t Token) Species {
|
|
|
|
- return MakeSpecies("default")
|
|
|
|
|
|
+func (DefaultMapper) Map(r Rule) Species {
|
|
|
|
+ return MakeSpecies(r.Name())
|
|
}
|
|
}
|
|
|
|
|
|
type Parser struct {
|
|
type Parser struct {
|
|
@@ -84,7 +84,7 @@ func (p *Parser) ParseTerminal(term Terminal) error {
|
|
if tok == nil {
|
|
if tok == nil {
|
|
return p.MakeError("Expected token kind: %d", term.Kind)
|
|
return p.MakeError("Expected token kind: %d", term.Kind)
|
|
}
|
|
}
|
|
- spec := p.Map(tok)
|
|
|
|
|
|
+ spec := p.Map(term)
|
|
NewChild(p.Now, spec, tok)
|
|
NewChild(p.Now, spec, tok)
|
|
// now should alreqdy be of suitable kind to accept a terminal token child.
|
|
// now should alreqdy be of suitable kind to accept a terminal token child.
|
|
return nil
|
|
return nil
|
|
@@ -108,8 +108,16 @@ func (p *Parser) PopUp() {
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+func (p *Parser) ParseReference(ref Reference) error {
|
|
|
|
+ rule, err := ref.Resolve()
|
|
|
|
+ if err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ return p.ParseRule(rule)
|
|
|
|
+}
|
|
|
|
+
|
|
func (p *Parser) ParseSequence(seq Sequence) error {
|
|
func (p *Parser) ParseSequence(seq Sequence) error {
|
|
- spec := p.Map(p.Token())
|
|
|
|
|
|
+ spec := p.Map(seq)
|
|
p.Now = NewChild(p.Now, spec, p.Token())
|
|
p.Now = NewChild(p.Now, spec, p.Token())
|
|
defer p.PopUp()
|
|
defer p.PopUp()
|
|
for _, rule := range seq.Rules {
|
|
for _, rule := range seq.Rules {
|
|
@@ -122,12 +130,12 @@ func (p *Parser) ParseSequence(seq Sequence) error {
|
|
return nil
|
|
return nil
|
|
}
|
|
}
|
|
|
|
|
|
-func (p *Parser) ParseAlternates(alt Alternates) error {
|
|
|
|
- spec := p.Map(p.Token())
|
|
|
|
- p.Now = NewChild(p.Now, spec, p.Token())
|
|
|
|
- defer p.PopUp()
|
|
|
|
- errors := []error{}
|
|
|
|
|
|
+/*
|
|
|
|
+func (p *Parser) ParseOptinalAlternates(alt Alternates) error {
|
|
for _, rule := range alt.Rules {
|
|
for _, rule := range alt.Rules {
|
|
|
|
+ if IsReference(rule) {
|
|
|
|
+
|
|
|
|
+ }
|
|
err := p.ParseRule(rule)
|
|
err := p.ParseRule(rule)
|
|
if err != nil {
|
|
if err != nil {
|
|
errors = append(errors, err)
|
|
errors = append(errors, err)
|
|
@@ -139,6 +147,37 @@ func (p *Parser) ParseAlternates(alt Alternates) error {
|
|
p.Errors = append(p.Errors, errors...)
|
|
p.Errors = append(p.Errors, errors...)
|
|
return p.MakeError("Could not parse alternate.")
|
|
return p.MakeError("Could not parse alternate.")
|
|
}
|
|
}
|
|
|
|
+*/
|
|
|
|
+
|
|
|
|
+func (p *Parser) ParseAlternates(alt Alternates) error {
|
|
|
|
+ spec := p.Map(alt)
|
|
|
|
+ p.Now = NewChild(p.Now, spec, p.Token())
|
|
|
|
+ defer p.PopUp()
|
|
|
|
+ errors := []error{}
|
|
|
|
+ hasEpsilon := false
|
|
|
|
+
|
|
|
|
+ for _, rule := range alt.Rules {
|
|
|
|
+ if IsEpsilon(rule) {
|
|
|
|
+ hasEpsilon = true
|
|
|
|
+ } else {
|
|
|
|
+ first, _ := rule.FirstSet()
|
|
|
|
+ if first.ContainsKind(p.Token().Kind()) {
|
|
|
|
+ err := p.ParseRule(rule)
|
|
|
|
+ if err != nil {
|
|
|
|
+ errors = append(errors, err)
|
|
|
|
+ } else { // this alternate was OK here.
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ if hasEpsilon { // No match is ok.
|
|
|
|
+ return nil
|
|
|
|
+ }
|
|
|
|
+ // If we get here no alternate was ok.
|
|
|
|
+ p.Errors = append(p.Errors, errors...)
|
|
|
|
+ return p.MakeError("Could not parse alternate.")
|
|
|
|
+}
|
|
|
|
|
|
func (p *Parser) ParseRule(r Rule) error {
|
|
func (p *Parser) ParseRule(r Rule) error {
|
|
p.Recursion++
|
|
p.Recursion++
|