aboutsummaryrefslogtreecommitdiff
path: root/grammar
diff options
context:
space:
mode:
Diffstat (limited to 'grammar')
-rw-r--r--grammar/follow.go60
-rw-r--r--grammar/follow_test.go3
-rw-r--r--grammar/grammar.go25
-rw-r--r--grammar/parsing_table.go4
-rw-r--r--grammar/production.go4
-rw-r--r--grammar/symbol.go5
-rw-r--r--grammar/symbol_test.go18
7 files changed, 31 insertions, 88 deletions
diff --git a/grammar/follow.go b/grammar/follow.go
index f835bba..67e5f70 100644
--- a/grammar/follow.go
+++ b/grammar/follow.go
@@ -87,20 +87,6 @@ func (flw *followSet) find(sym symbol) (*followEntry, error) {
return e, nil
}
-type followComContext struct {
- prods *productionSet
- first *firstSet
- follow *followSet
-}
-
-func newFollowComContext(prods *productionSet, first *firstSet) *followComContext {
- return &followComContext{
- prods: prods,
- first: first,
- follow: newFollow(prods),
- }
-}
-
func genFollowSet(prods *productionSet, first *firstSet) (*followSet, error) {
ntsyms := map[symbol]struct{}{}
for _, prod := range prods.getAllProductions() {
@@ -110,11 +96,11 @@ func genFollowSet(prods *productionSet, first *firstSet) (*followSet, error) {
ntsyms[prod.lhs] = struct{}{}
}
- cc := newFollowComContext(prods, first)
+ follow := newFollow(prods)
for {
more := false
for ntsym := range ntsyms {
- e, err := cc.follow.find(ntsym)
+ e, err := follow.find(ntsym)
if err != nil {
return nil, err
}
@@ -138,7 +124,7 @@ func genFollowSet(prods *productionSet, first *firstSet) (*followSet, error) {
more = true
}
if fst.empty {
- flw, err := cc.follow.find(prod.lhs)
+ flw, err := follow.find(prod.lhs)
if err != nil {
return nil, err
}
@@ -155,43 +141,5 @@ func genFollowSet(prods *productionSet, first *firstSet) (*followSet, error) {
}
}
- return cc.follow, nil
-}
-
-func genFollowEntry(cc *followComContext, acc *followEntry, ntsym symbol) (bool, error) {
- changed := false
-
- if ntsym.isStart() {
- added := acc.addEOF()
- if added {
- changed = true
- }
- }
- for _, prod := range cc.prods.getAllProductions() {
- for i, sym := range prod.rhs {
- if sym != ntsym {
- continue
- }
- fst, err := cc.first.find(prod, i+1)
- if err != nil {
- return false, err
- }
- added := acc.merge(fst, nil)
- if added {
- changed = true
- }
- if fst.empty {
- flw, err := cc.follow.find(prod.lhs)
- if err != nil {
- return false, err
- }
- added := acc.merge(nil, flw)
- if added {
- changed = true
- }
- }
- }
- }
-
- return changed, nil
+ return follow, nil
}
diff --git a/grammar/follow_test.go b/grammar/follow_test.go
index ba2d973..af3f064 100644
--- a/grammar/follow_test.go
+++ b/grammar/follow_test.go
@@ -158,6 +158,9 @@ func genActualFollow(t *testing.T, src string) (*followSet, *Grammar) {
t.Fatal(err)
}
flw, err := genFollowSet(gram.productionSet, fst)
+ if err != nil {
+ t.Fatal(err)
+ }
if flw == nil {
t.Fatal("genFollow returned nil without any error")
}
diff --git a/grammar/grammar.go b/grammar/grammar.go
index 2294219..7dbd0ed 100644
--- a/grammar/grammar.go
+++ b/grammar/grammar.go
@@ -116,7 +116,7 @@ func (b *GrammarBuilder) Build() (*Grammar, error) {
if len(md.Parameters) != 1 || md.Parameters[0].ID == "" {
b.errs = append(b.errs, &verr.SpecError{
Cause: semErrMDInvalidParam,
- Detail: fmt.Sprintf("'name' takes just one ID parameter"),
+ Detail: "'name' takes just one ID parameter",
Row: md.Pos.Row,
Col: md.Pos.Col,
})
@@ -480,7 +480,7 @@ func genLexEntry(prod *spec.ProductionNode) (*mlspec.LexEntry, bool, string, *ve
if len(dir.Parameters) == 0 {
return nil, false, "", &verr.SpecError{
Cause: semErrDirInvalidParam,
- Detail: fmt.Sprintf("'mode' directive needs an ID parameter"),
+ Detail: "'mode' directive needs an ID parameter",
Row: dir.Pos.Row,
Col: dir.Pos.Col,
}, nil
@@ -489,7 +489,7 @@ func genLexEntry(prod *spec.ProductionNode) (*mlspec.LexEntry, bool, string, *ve
if param.ID == "" {
return nil, false, "", &verr.SpecError{
Cause: semErrDirInvalidParam,
- Detail: fmt.Sprintf("'mode' directive needs an ID parameter"),
+ Detail: "'mode' directive needs an ID parameter",
Row: param.Pos.Row,
Col: param.Pos.Col,
}, nil
@@ -528,7 +528,7 @@ func genLexEntry(prod *spec.ProductionNode) (*mlspec.LexEntry, bool, string, *ve
if len(dir.Parameters) > 0 {
return nil, false, "", &verr.SpecError{
Cause: semErrDirInvalidParam,
- Detail: fmt.Sprintf("'skip' directive needs no parameter"),
+ Detail: "'skip' directive needs no parameter",
Row: dir.Pos.Row,
Col: dir.Pos.Col,
}, nil
@@ -538,7 +538,7 @@ func genLexEntry(prod *spec.ProductionNode) (*mlspec.LexEntry, bool, string, *ve
if len(dir.Parameters) != 1 || dir.Parameters[0].ID == "" {
return nil, false, "", &verr.SpecError{
Cause: semErrDirInvalidParam,
- Detail: fmt.Sprintf("'push' directive needs an ID parameter"),
+ Detail: "'push' directive needs an ID parameter",
Row: dir.Pos.Row,
Col: dir.Pos.Col,
}, nil
@@ -548,7 +548,7 @@ func genLexEntry(prod *spec.ProductionNode) (*mlspec.LexEntry, bool, string, *ve
if len(dir.Parameters) > 0 {
return nil, false, "", &verr.SpecError{
Cause: semErrDirInvalidParam,
- Detail: fmt.Sprintf("'pop' directive needs no parameter"),
+ Detail: "'pop' directive needs no parameter",
Row: dir.Pos.Row,
Col: dir.Pos.Col,
}, nil
@@ -558,7 +558,7 @@ func genLexEntry(prod *spec.ProductionNode) (*mlspec.LexEntry, bool, string, *ve
if len(dir.Parameters) != 1 || dir.Parameters[0].String == "" {
return nil, false, "", &verr.SpecError{
Cause: semErrDirInvalidParam,
- Detail: fmt.Sprintf("'alias' directive needs a string parameter"),
+ Detail: "'alias' directive needs a string parameter",
Row: dir.Pos.Row,
Col: dir.Pos.Col,
}, nil
@@ -762,7 +762,7 @@ func (b *GrammarBuilder) genProductionsAndActions(root *spec.RootNode, symTabAnd
if len(dir.Parameters) != 1 || dir.Parameters[0].Tree == nil {
b.errs = append(b.errs, &verr.SpecError{
Cause: semErrDirInvalidParam,
- Detail: fmt.Sprintf("'ast' directive needs a tree parameter"),
+ Detail: "'ast' directive needs a tree parameter",
Row: dir.Pos.Row,
Col: dir.Pos.Col,
})
@@ -829,7 +829,7 @@ func (b *GrammarBuilder) genProductionsAndActions(root *spec.RootNode, symTabAnd
if len(dir.Parameters) != 1 || dir.Parameters[0].ID == "" {
b.errs = append(b.errs, &verr.SpecError{
Cause: semErrDirInvalidParam,
- Detail: fmt.Sprintf("'prec' directive needs an ID parameter"),
+ Detail: "'prec' directive needs an ID parameter",
Row: dir.Pos.Row,
Col: dir.Pos.Col,
})
@@ -859,7 +859,7 @@ func (b *GrammarBuilder) genProductionsAndActions(root *spec.RootNode, symTabAnd
if len(dir.Parameters) > 0 {
b.errs = append(b.errs, &verr.SpecError{
Cause: semErrDirInvalidParam,
- Detail: fmt.Sprintf("'recover' directive needs no parameter"),
+ Detail: "'recover' directive needs no parameter",
Row: dir.Pos.Row,
Col: dir.Pos.Col,
})
@@ -1140,7 +1140,10 @@ func Compile(gram *Grammar, opts ...CompileOption) (*spec.CompiledGrammar, error
return nil, err
}
- f.Write(d)
+ _, err = f.Write(d)
+ if err != nil {
+ return nil, fmt.Errorf("failed to write a description file: %w", err)
+ }
}
if len(b.conflicts) > 0 {
diff --git a/grammar/parsing_table.go b/grammar/parsing_table.go
index 28f6392..0b858fb 100644
--- a/grammar/parsing_table.go
+++ b/grammar/parsing_table.go
@@ -56,10 +56,6 @@ func newGoToEntry(state stateNum) goToEntry {
return goToEntry(state)
}
-func (e goToEntry) isEmpty() bool {
- return e == goToEntryEmpty
-}
-
func (e goToEntry) describe() (GoToType, stateNum) {
if e == goToEntryEmpty {
return GoToTypeError, stateNumInitial
diff --git a/grammar/production.go b/grammar/production.go
index d4ea7a1..87b392f 100644
--- a/grammar/production.go
+++ b/grammar/production.go
@@ -58,10 +58,6 @@ func newProduction(lhs symbol, rhs []symbol) (*production, error) {
}, nil
}
-func (p *production) equals(q *production) bool {
- return q.id == p.id
-}
-
func (p *production) isEmpty() bool {
return p.rhsLen == 0
}
diff --git a/grammar/symbol.go b/grammar/symbol.go
index 3a7dfb6..ee58737 100644
--- a/grammar/symbol.go
+++ b/grammar/symbol.go
@@ -122,10 +122,7 @@ func (s symbol) isNonTerminal() bool {
return false
}
kind, _, _, _ := s.describe()
- if kind == symbolKindNonTerminal {
- return true
- }
- return false
+ return kind == symbolKindNonTerminal
}
func (s symbol) isTerminal() bool {
diff --git a/grammar/symbol_test.go b/grammar/symbol_test.go
index fda3ddf..0cf2a06 100644
--- a/grammar/symbol_test.go
+++ b/grammar/symbol_test.go
@@ -4,15 +4,15 @@ import "testing"
func TestSymbol(t *testing.T) {
tab := newSymbolTable()
- tab.registerStartSymbol("expr'")
- tab.registerNonTerminalSymbol("expr")
- tab.registerNonTerminalSymbol("term")
- tab.registerNonTerminalSymbol("factor")
- tab.registerTerminalSymbol("id")
- tab.registerTerminalSymbol("add")
- tab.registerTerminalSymbol("mul")
- tab.registerTerminalSymbol("l_paren")
- tab.registerTerminalSymbol("r_paren")
+ _, _ = tab.registerStartSymbol("expr'")
+ _, _ = tab.registerNonTerminalSymbol("expr")
+ _, _ = tab.registerNonTerminalSymbol("term")
+ _, _ = tab.registerNonTerminalSymbol("factor")
+ _, _ = tab.registerTerminalSymbol("id")
+ _, _ = tab.registerTerminalSymbol("add")
+ _, _ = tab.registerTerminalSymbol("mul")
+ _, _ = tab.registerTerminalSymbol("l_paren")
+ _, _ = tab.registerTerminalSymbol("r_paren")
nonTermTexts := []string{
"", // Nil