-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcontext.go
130 lines (115 loc) · 4.33 KB
/
context.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package main
import "container/list"
type OpContext struct {
// the tree used to find the token for a given operator
opTree *OperatorTree
// the list of all precedence levels used in a particular parsing session
precedenceList *list.List
opToken int
}
func NewOpContext() *OpContext {
r := new(OpContext)
r.opTree = NewOperatorTree()
r.precedenceList = list.New()
r.opToken = INIT_TOKEN
r.opTree.AddOperatorRune(EOF_RUNE, EOF_TOKEN, 0)
r.opTree.AddOperatorRune(NEWLINE_RUNE, NEWLINE_TOKEN, NEWLINE_FLAG)
return r
}
// AddOperator adds a new operator to the current context and the given precedence level.
// It returns a pointer to the properties of the generated operator, if generation was successful.
func (ctx *OpContext) AddOperator(symbols []string, precedenceLevel *PrecedenceLevel, codeBlockArguments uint, argumentCount int) *OpProp {
var op string
if len(symbols) == 0 {
op = ""
} else {
op = symbols[0]
symbols = symbols[1:]
}
var success bool
var token int
// for the NIL operator, we don't actually want to generate a new token,
// we just want to generate its properties.
if op == "" {
token, success = 0, true
} else {
token, success = ctx.addOperatorToken([]rune(op))
}
subsequentSymbols := make([]int, len(symbols))
for i, symbol := range symbols {
newToken, newSuccess := ctx.addOperatorToken([]rune(symbol))
success = success && newSuccess
subsequentSymbols[i] = newToken
}
if success {
properties := new(OpProp)
properties.argumentCount = argumentCount
properties.codeBlockArguments = codeBlockArguments
properties.subsequentSymbols = subsequentSymbols
properties.initSymbol = op // for debugging purposes
precedenceLevel.operators[token] = properties
return properties
}
return nil
}
// addOperatorToken adds a new operator symbol to the operator tree.
// Returns the generated token for this new symbol.
func (ctx *OpContext) addOperatorToken(op []rune) (int, bool) {
token := ctx.opToken
newToken := ctx.opTree.GetToken(op)
// in the case of symbols with multiple interpretations
// such as : in case _: and _ ? _ : _,
// we should leave the token unchanged.
if newToken != NIL_TOKEN {
token = newToken
}
success := ctx.opTree.AddOperator(op, token, 0)
if success && token == ctx.opToken {
ctx.opToken++
}
return token, success
}
func (ctx *OpContext) AddOperatorAt(symbols []string, precedence int, codeBlockArguments uint, argumentCount int) *OpProp {
precedenceListElement := ctx.precedenceList.Front()
for i := 0; i < precedence; i++ {
precedenceListElement = precedenceListElement.Next()
}
return ctx.AddOperator(symbols, precedenceListElement.Value.(*PrecedenceLevel), codeBlockArguments, argumentCount)
}
func (ctx *OpContext) AddOperatorToLowest(symbols []string, codeBlockArguments uint, argumentCount int) *OpProp {
precedenceListElement := ctx.precedenceList.Front()
return ctx.AddOperator(symbols, precedenceListElement.Value.(*PrecedenceLevel), codeBlockArguments, argumentCount)
}
func (ctx *OpContext) AddOperatorToHighest(symbols []string, codeBlockArguments uint, argumentCount int) *OpProp {
precedenceListElement := ctx.precedenceList.Back()
return ctx.AddOperator(symbols, precedenceListElement.Value.(*PrecedenceLevel), codeBlockArguments, argumentCount)
}
func (ctx *OpContext) AddControlOperator(op []rune, flags uint) bool {
success := ctx.opTree.AddOperator(op, ctx.opToken, flags)
if success {
ctx.opToken++
}
return success
}
func (ctx *OpContext) AddFixedTokenOperator(op []rune, token int, flags uint) bool {
return ctx.opTree.AddOperator(op, token, flags)
}
func (ctx *OpContext) RenameOperator(oldName []rune, newName []rune) {
oldBranch := ctx.opTree.GetBranch(oldName)
token := oldBranch.operatorToken
oldBranch.operatorToken = NIL_TOKEN
newBranch := ctx.opTree.GetBranch(newName)
newBranch.operatorToken = token
}
func (ctx *OpContext) AddLowestPrecedenceLevel(precedenceLevel *PrecedenceLevel) {
ctx.precedenceList.PushFront(precedenceLevel)
}
func (ctx *OpContext) AddHighestPrecedenceLevel(precedenceLevel *PrecedenceLevel) {
ctx.precedenceList.PushBack(precedenceLevel)
}
func (ctx *OpContext) AddLowerPrecedenceLevel(level *PrecedenceLevel, mark *list.Element) {
ctx.precedenceList.InsertBefore(level, mark)
}
func (ctx *OpContext) AddHigherPrecedenceLevel(level *PrecedenceLevel, mark *list.Element) {
ctx.precedenceList.InsertAfter(level, mark)
}