-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparser.go
107 lines (83 loc) · 2.03 KB
/
parser.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package parser
import "fmt"
type ParserTable interface {
DetectTok(str string) (Token, string, int)
ActionTable(sym, st Token) (action Action, state Token, nReduce int)
TableGoto(uncovered, lhs Token) Token
TableReduceCustom(eState Token, tail Stack) Stack
TableRecover(s, term Token, st *Stack, termStr string) (Token, string)
}
// https://slideplayer.com/slide/8029737/
// see p24
type Parser struct {
c int
st Stack
in string
parserTable ParserTable
}
func NewParser(parserTable ParserTable) *Parser {
return &Parser{
c: 0,
st: make(Stack, 0),
parserTable: parserTable,
}
}
func (p *Parser) Reset() {
p.st.clear()
p.c = 0
p.in = ""
return
}
func (p *Parser) PrintDump() {
fmt.Println("Dump >", p.st.dumpStr())
return
}
func (p *Parser) GetState() Stack {
return p.st
}
func (p *Parser) peekToken() (Token, string) {
t, res, i := p.parserTable.DetectTok(p.in[p.c:])
p.c += i
// fmt.Printf("peekToken > '%v' -> %v i=%d\n", res, t.String(), i)
return t, res
}
/* Parse parses a line of text */
func (p *Parser) Parse(in string) Action {
p.in = in
p.st.Push(newTokRec(Beg))
term, termStr := p.peekToken()
for {
s := p.st.peek()
eAct, eState, eNPop := p.parserTable.ActionTable(term, s)
switch eAct {
case ActShift:
p.st.Push(newTokRecStr(term, termStr))
p.st.Push(newTokRec(eState))
term, termStr = p.peekToken()
case ActReduce:
tail := p.st.Pop(eNPop)
uncovered := p.st.peek()
tailNew := p.parserTable.TableReduceCustom(eState, tail)
p.st.Push(newTokRecChildren(eState, tailNew))
newState := p.parserTable.TableGoto(uncovered, eState)
if newState == None {
return eAct
}
p.st.Push(newTokRec(newState))
case ActAccept:
return eAct
case ActNone:
termNew, termStrNew := p.parserTable.TableRecover(s, term, &p.st, termStr)
if termNew != TokUndefined {
term = termNew
termStr = termStrNew
continue
}
return eAct
default:
fmt.Println("Unexpected state >")
return eAct
}
}
return ActNone
}