/
mss.go
111 lines (91 loc) · 2.25 KB
/
mss.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
// Package mss implements a CartoCSS parser and rule generator.
package mss
import "math"
type Value interface{}
type MSS struct {
root block
stack []*block
base block
}
// Map returns properties of the root Map{} block.
func (m *MSS) Map() *Properties {
if m.base.properties != nil {
return m.base.properties
}
return &Properties{}
}
func (m *MSS) current() *block {
return m.stack[len(m.stack)-1]
}
func newMSS() *MSS {
m := MSS{}
m.stack = []*block{&m.root}
return &m
}
func (m *MSS) addLayer(layer string) {
s := m.current().currentSelector()
s.Layer = layer
}
func (m *MSS) addAttachment(attachment string) {
s := m.current().currentSelector()
s.Attachment = attachment
}
func (m *MSS) addClass(class string) {
s := m.current().currentSelector()
s.Class = class
}
func (m *MSS) addFilter(field string, compOp CompOp, value interface{}) {
s := m.current().currentSelector()
f := Filter{field, compOp, value}
s.Filters = append(s.Filters, f)
}
func (m *MSS) addZoom(comp CompOp, level int64) {
if level > math.MaxInt8 || level < 0 {
// TODO
panic("zoom not between 0 and 30")
}
s := m.current().currentSelector()
if s.Zoom != InvalidZoom {
s.Zoom = s.Zoom.add(comp, int8(level))
} else {
s.Zoom = NewZoomRange(comp, level)
}
}
func (m *MSS) pushSelector() {
b := m.current()
b.selectors = append(b.selectors, &Selector{Zoom: AllZoom})
}
func (m *MSS) setProperty(property string, val Value, pos position) {
m.current().addProperty(property, val, pos)
}
func (m *MSS) setInstance(instance string) {
m.current().instance = instance
}
func (m *MSS) pushMapBlock() {
m.stack = append(m.stack, &m.base)
}
func (m *MSS) pushBlock() {
b := &block{}
current := m.stack[len(m.stack)-1]
current.blocks = append(current.blocks, b)
m.stack = append(m.stack, b)
}
func (m *MSS) popBlock() {
m.stack = m.stack[:len(m.stack)-1]
}
type block struct {
selectors []*Selector
properties *Properties
instance string
blocks []*block
}
func (b *block) addProperty(property string, val Value, pos position) {
if b.properties == nil {
b.properties = &Properties{}
}
b.properties.setPos(key{name: property, instance: b.instance}, val, pos)
b.instance = ""
}
func (b *block) currentSelector() *Selector {
return b.selectors[len(b.selectors)-1]
}