123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- // Uses an ll1 grammar to parse an input from an ll1 flexer to an Ast.
- package parser
- // import "fmt"
- import . "src.eruta.nl/beoran/ll1/common"
- import . "src.eruta.nl/beoran/ll1/ast"
- import . "src.eruta.nl/beoran/ll1/grammar"
- import . "src.eruta.nl/beoran/ll1/flexer"
- // A TokenMapper maps a token to a Species.
- type TokenMapper interface {
- // Returns the species to use for the grammar rule. If nil, the token
- // may be skipped.
- Map(t Rule) Species
- }
- type DefaultMapper struct{}
- func (DefaultMapper) Map(r Rule) Species {
- return MakeSpecies(r.Name())
- }
- type Parser struct {
- Grammar
- TokenMapper
- Tokens []Token
- Index int
- Errors []error
- Result Ast
- // current location in the ast being built.
- Now Ast
- Recursion int
- }
- func (p *Parser) MakeError(msg string, args ...interface{}) error {
- return MakeErrorToken(p.Token().Location(), msg, args...)
- }
- func (p *Parser) AddError(msg string, args ...interface{}) error {
- err := MakeErrorToken(p.Token().Location(), msg, args...)
- p.Errors = append(p.Errors, err)
- return err
- }
- func (g Parser) Token() Token {
- if g.Index < len(g.Tokens) {
- return g.Tokens[g.Index]
- }
- last := g.Tokens[len(g.Tokens)-1]
- return MakeErrorToken(last.Location(), "Unexpected end of input.")
- }
- func (g *Parser) Expect(kind Kind) Token {
- tok := g.Token()
- if tok.Kind() == kind {
- g.Index++
- return tok
- }
- return nil
- }
- func (g *Parser) Accept(kinds ...Kind) Token {
- tok := g.Token()
- for _, kind := range kinds {
- if tok.Kind() == kind {
- g.Index++
- return tok
- }
- }
- return nil
- }
- func (g *Parser) Require(kinds ...Kind) Token {
- tok := g.Accept(kinds...)
- if tok != nil {
- return tok
- }
- g.AddError("Expected: %v", kinds)
- return nil
- }
- func (p *Parser) ParseTerminal(term Terminal) error {
- tok := p.Expect(term.Kind)
- if tok == nil {
- return p.MakeError("Expected token kind: %d", term.Kind)
- }
- spec := p.Map(term)
- NewChild(p.Now, spec, tok)
- // now should alreqdy be of suitable kind to accept a terminal token child.
- return nil
- }
- func (g *Parser) ParseEpsilon(term Epsilon) error {
- return nil
- }
- func (p *Parser) ParseEnd(term EndOfInput) error {
- if p.Index >= (len(p.Tokens) - 1) {
- p.Index = len(p.Tokens) // reach the end.
- return nil
- } else {
- return p.MakeError("Expected end of input.")
- }
- }
- func (p *Parser) PopUp() {
- if p.Now != nil && p.Now.Parent() != nil {
- p.Now = p.Now.Parent()
- }
- }
- 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 {
- spec := p.Map(seq)
- p.Now = NewChild(p.Now, spec, p.Token())
- defer p.PopUp()
- for _, rule := range seq.Rules {
- err := p.ParseRule(rule)
- if err != nil {
- p.Errors = append(p.Errors, err)
- return err
- }
- }
- return nil
- }
- /*
- func (p *Parser) ParseOptinalAlternates(alt Alternates) error {
- for _, rule := range alt.Rules {
- if IsReference(rule) {
- }
- err := p.ParseRule(rule)
- if err != nil {
- errors = append(errors, err)
- } else { // one alternate was OK here.
- 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) 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 {
- p.Recursion++
- if p.Recursion > 800 {
- panic("Too much recursion in grammar.")
- }
- switch rv := r.(type) {
- case Epsilon:
- p.ParseEpsilon(rv)
- case EndOfInput:
- p.ParseEnd(rv)
- case Terminal:
- p.ParseTerminal(rv)
- case Alternates:
- p.ParseAlternates(rv)
- case Sequence:
- p.ParseSequence(rv)
- case Reference:
- p.ParseReference(rv)
- default:
- panic("Unknown rule type in ParseRule.")
- }
- // p.Now.AddChild()
- return nil
- }
- func (p *Parser) Parse(input []Token) error {
- p.Tokens = input
- p.Recursion = 0
- p.Errors = []error{}
- p.Result = NewAstNone()
- p.Now = p.Result
- return p.ParseRule(p.Grammar.Top)
- return nil
- }
|