Skip to content

Commit

Permalink
Grammar,Parser,Symbol: add infinate recursive check #8
Browse files Browse the repository at this point in the history
  • Loading branch information
acekingke committed Dec 8, 2022
1 parent af1fdd2 commit 56dda32
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 3 deletions.
43 changes: 43 additions & 0 deletions Grammar/grammar.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ func (g *Grammar) CalculateEpsilonClosure() {
if every_isEpsilon {
if !(r.LeftPart.IsEpsilonClosure) {
r.LeftPart.IsEpsilonClosure = true
// epsilon is terminate too
r.LeftPart.CanTerminate = true
change++
}
}
Expand All @@ -95,6 +97,47 @@ func (g *Grammar) CalculateEpsilonClosure() {
}
}
}

//calculate all epsilon
func (g *Grammar) CalculateCanTerminate() []*symbol.Symbol {
change := 0
for {
change = 0
for _, r := range g.ProductoinRules {
//for every sym in RightPart, is IsEpsilonClosure, Is EpsilonClosure
//empty is true
every_CanTerm := true
for _, every_sy := range r.RighPart {
every_CanTerm = every_CanTerm && every_sy.CanTerminate
}
if every_CanTerm {
if !(r.LeftPart.CanTerminate) {
r.LeftPart.CanTerminate = true
change++
}
}
}
if change == 0 {
break
}
}
var inf_cycles []*symbol.Symbol
for sy := range g.VnSet {
if !sy.CanTerminate {
inf_cycles = append(inf_cycles, sy)
}
}
return inf_cycles
}

func (g Grammar) PrintInfLoop(some []*symbol.Symbol) {
fmt.Println("Error:")
for _, s := range some {
fmt.Printf("%s ", s.Name)
}
fmt.Println(" have Infinite recursion loop")
}

func (g Grammar) ShowAllSymbols() {
for _, s := range g.Symbols {
s.Show()
Expand Down
34 changes: 34 additions & 0 deletions Parser/Parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ func TestParser2(t *testing.T) {
%start s
%%
s : A
`
if tr, err := Parse(str); err != nil {
t.Error(err)
Expand Down Expand Up @@ -233,3 +234,36 @@ func TestParser3(t *testing.T) {
root.LALR1 = lalr
}
}

func TestParserInifLoop(t *testing.T) {
defer func() {
if r := recover(); r == nil {
t.Errorf("The code did not panic")
}
}()
str := `
%{
package main
%}
%left <tga> A B
%left C
%start s
%%
s : A
A : B
B : A
%%
`
if tr, err := Parse(str); err != nil {
t.Error(err)
} else {
// work in test
var node Node = tr
w := DoWalker(&node, &RootVistor{})
lalr := w.BuildLALR1()
fmt.Println(lalr)
root := w.VistorNode.(*RootVistor)
root.LALR1 = lalr
}
}
8 changes: 6 additions & 2 deletions Parser/Vistor.go
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,8 @@ func (v *astDeclareVistor) Process(node *Node) {
Value: 0,
}
v.idsymtabl[n.StartSym] = id
v.startSym = v.idsymtabl[n.StartSym]
}

v.startSym = v.idsymtabl[n.StartSym]
//set other value
v.code = n.CodeList
v.union = n.Union
Expand Down Expand Up @@ -319,6 +318,11 @@ func (w *Walker) BuildLALR1() *lalr.LALR1 {
}
g.ResolveSymbols()
g.CalculateEpsilonClosure()
if infLoop := g.CalculateCanTerminate(); len(infLoop) != 0 {
g.PrintInfLoop(infLoop)
panic("Dected infinite loop")
}

item_var := item.NewItem(0, 0)
Icloures := item.NewItemCloure()
Icloures.InsertItem(item_var)
Expand Down
4 changes: 3 additions & 1 deletion Symbol/symbol.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ type Symbol struct {
Tag string // Tag indicate the type of symbol
IsNonTerminator bool
IsEpsilonClosure bool
CanTerminate bool //check weather is has inf loop
PrecType E_Precedence
Prec int
}

func NewSymbol(id uint, name string) *Symbol {
return &Symbol{ID: id, Name: name, PrecType: NONE, Prec: -1}
return &Symbol{ID: id, Name: name, PrecType: NONE, Prec: -1, CanTerminate: true}
}

func (s *Symbol) SetValue(val int) {
Expand All @@ -43,6 +44,7 @@ func (s *Symbol) GetTag() string {

func (s *Symbol) SetNT() {
s.IsNonTerminator = true
s.CanTerminate = false
}

func (s *Symbol) SetEpsilon() {
Expand Down

0 comments on commit 56dda32

Please sign in to comment.