Skip to content

Commit 581b1d6

Browse files
committed
Fixed ambigious grammar rules, fixed interpreter
1 parent 6a32196 commit 581b1d6

9 files changed

Lines changed: 814 additions & 748 deletions

File tree

model/BuildCollection.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package model
22

3-
import "sort"
3+
import (
4+
"encoding/json"
5+
"log"
6+
"sort"
7+
)
48

59
type BuildCollection struct {
610
Set Set
@@ -23,6 +27,7 @@ func (b *BuildCollection) Sort() *BuildCollection {
2327
return b
2428
}
2529

30+
// HasMissingParts returns true if there are parts missing in the BuildCollection.
2631
func (b *BuildCollection) HasMissingParts() bool {
2732
for _, entry := range b.Mapping {
2833
if entry.Quantity > 0 {
@@ -33,6 +38,7 @@ func (b *BuildCollection) HasMissingParts() bool {
3338
return false
3439
}
3540

41+
// CountMissingParts counts all parts that are still missing in the BuildCollection.
3642
func (b *BuildCollection) CountMissingParts() int {
3743
var missing int
3844
for _, entry := range b.Mapping {
@@ -42,6 +48,7 @@ func (b *BuildCollection) CountMissingParts() int {
4248
return missing
4349
}
4450

51+
// CountProvidedParts counts all parts that are provided in the BuildCollection, including substitutes.
4552
func (b *BuildCollection) CountProvidedParts() int {
4653
var provided int
4754
for _, entry := range b.Mapping {
@@ -53,10 +60,28 @@ func (b *BuildCollection) CountProvidedParts() int {
5360
return provided
5461
}
5562

63+
// Save writes the BuildCollection into a JSON encoded file. In case of an error it terminates with a fatal log entry.
5664
func (b BuildCollection) Save(filePath string) {
5765
Save(b, filePath)
5866
}
5967

68+
// Print outputs a human-readable representation of the BuildCollection to the standard output.
6069
func (b BuildCollection) Print() {
6170
Print(b)
6271
}
72+
73+
// Clone creates a deep copy of the BuildCollection and returns it as a CollectionType.
74+
func (b BuildCollection) Clone() CollectionType {
75+
origJSON, err := json.Marshal(b)
76+
if err != nil {
77+
log.Fatalf(CLONING_FAILED_MSG, err.Error())
78+
}
79+
80+
clone := new(BuildCollection)
81+
err = json.Unmarshal(origJSON, clone)
82+
if err != nil {
83+
log.Fatalf(CLONING_FAILED_MSG, err.Error())
84+
}
85+
86+
return *clone
87+
}

model/Collection.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package model
22

33
import (
4+
"encoding/json"
5+
"log"
46
"sort"
57

68
"github.com/google/go-cmp/cmp"
@@ -179,14 +181,32 @@ func (c *Collection) MapPartsByPartNumber(keyMapping func(string) string) map[st
179181
return partsMap
180182
}
181183

184+
// Save writes the Collection into a JSON encoded file. In case of an error it terminates with a fatal log entry.
182185
func (c Collection) Save(filePath string) {
183186
Save(c, filePath)
184187
}
185188

189+
// Print outputs a human-readable representation of the Collection to the standard output.
186190
func (c Collection) Print() {
187191
Print(c)
188192
}
189193

194+
// Clone creates a deep copy of the Collection and returns it as a CollectionType.
195+
func (b Collection) Clone() CollectionType {
196+
origJSON, err := json.Marshal(b)
197+
if err != nil {
198+
log.Fatalf(CLONING_FAILED_MSG, err.Error())
199+
}
200+
201+
clone := new(Collection)
202+
err = json.Unmarshal(origJSON, clone)
203+
if err != nil {
204+
log.Fatalf(CLONING_FAILED_MSG, err.Error())
205+
}
206+
207+
return *clone
208+
}
209+
190210
func (c *Collection) setParts(partsMap map[string][]Part) {
191211
newParts := []Part{}
192212
for key, value := range partsMap {

model/CollectionType.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ package model
33
type CollectionType interface {
44
Save(filePath string)
55
Print()
6+
Clone() CollectionType
67
}

scripting/bricksInterpreter.go

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ func (b *bricksInterpreter) ExitBuild(ctx *parser.BuildContext) {
8585
if neededCollection, ok := firstValue.(model.Collection); ok {
8686
if providedCollection, ok := secondValue.(model.Collection); ok {
8787
result := services.Build(&neededCollection, &providedCollection, mode)
88-
b.stack.push(result)
88+
b.stack.push(*result)
8989
} else {
9090
log.Fatal("The second operand of build must be a collection")
9191
return
@@ -101,7 +101,7 @@ func (b *bricksInterpreter) ExitIdentifier(ctx *parser.IdentifierContext) {
101101
if !ok {
102102
log.Fatalf("The variable '%s' is not defined", ctx.ID().GetText())
103103
}
104-
b.stack.push(model.DeepClone(value))
104+
b.stack.push(value.Clone())
105105
}
106106

107107
func (b *bricksInterpreter) ExitLoad(ctx *parser.LoadContext) {
@@ -115,29 +115,29 @@ func (b *bricksInterpreter) ExitLoad(ctx *parser.LoadContext) {
115115
func (b *bricksInterpreter) ExitImport_(ctx *parser.Import_Context) {
116116
filePath := strings.Trim(ctx.STRING().GetText(), "\"")
117117

118-
b.stack.push(services.ImportCSVCollection(filePath))
118+
b.stack.push(*services.ImportCSVCollection(filePath))
119119
}
120120

121121
func (b *bricksInterpreter) ExitAllParts(ctx *parser.AllPartsContext) {
122122
allParts := b.usersAPI.GetAllParts()
123-
b.stack.push(allParts)
123+
b.stack.push(*allParts)
124124
}
125125

126126
func (b *bricksInterpreter) ExitLost(ctx *parser.LostContext) {
127127
lostParts := b.usersAPI.GetLostParts()
128-
b.stack.push(lostParts)
128+
b.stack.push(*lostParts)
129129
}
130130

131131
func (b *bricksInterpreter) ExitSet(ctx *parser.SetContext) {
132132
includeMiniFigs := ctx.BOOL() != nil && ctx.BOOL().GetText() == "true"
133133
setParts := api.RetrieveSetParts(b.bricksAPI, ctx.SET_NUM().GetText(), includeMiniFigs)
134-
b.stack.push(setParts)
134+
b.stack.push(*setParts)
135135
}
136136

137137
func (b *bricksInterpreter) ExitUserSet(ctx *parser.UserSetContext) {
138138
includeMiniFigs := ctx.BOOL() != nil && ctx.BOOL().GetText() == "true"
139139
userSetParts := api.RetrieveUserSetParts(b.bricksAPI, b.usersAPI, ctx.SET_NUM().GetText(), includeMiniFigs)
140-
b.stack.push(userSetParts)
140+
b.stack.push(*userSetParts)
141141
}
142142

143143
func (b *bricksInterpreter) ExitSetList(ctx *parser.SetListContext) {
@@ -151,7 +151,7 @@ func (b *bricksInterpreter) ExitSetList(ctx *parser.SetListContext) {
151151
collection := services.MergeAllCollections(setListParts)
152152
collection.SortByColorAndName(false)
153153

154-
b.stack.push(collection)
154+
b.stack.push(*collection)
155155
}
156156

157157
func (b *bricksInterpreter) ExitPartList(ctx *parser.PartListContext) {
@@ -160,23 +160,23 @@ func (b *bricksInterpreter) ExitPartList(ctx *parser.PartListContext) {
160160
log.Fatal(err)
161161
}
162162
partListParts := b.usersAPI.GetPartListParts(uint(partListId))
163-
b.stack.push(partListParts)
163+
b.stack.push(*partListParts)
164164
}
165165

166166
func (b *bricksInterpreter) ExitPartLists(ctx *parser.PartListsContext) {
167167
filePath := strings.Trim(ctx.STRING().GetText(), "\"")
168168
includeNonBuildable := ctx.BOOL() != nil && ctx.BOOL().GetText() == "true"
169169
collections := api.RetrievePartListsParts(b.usersAPI, filePath, includeNonBuildable)
170170
collection := services.MergeAllCollections(collections)
171-
b.stack.push(collection)
171+
b.stack.push(*collection)
172172
}
173173

174174
func (b *bricksInterpreter) ExitSum(ctx *parser.SumContext) {
175175
log.Printf("Calculating sum")
176176

177177
sum := model.NewCollection()
178178

179-
for range ctx.AllCollectionExp() {
179+
for range ctx.AllCollectionOrId() {
180180
value := b.stack.pop()
181181
if summand, ok := value.(model.Collection); ok {
182182
sum.Add(&summand)
@@ -185,7 +185,7 @@ func (b *bricksInterpreter) ExitSum(ctx *parser.SumContext) {
185185
}
186186
}
187187

188-
b.stack.push(sum)
188+
b.stack.push(*sum)
189189
}
190190

191191
func (b *bricksInterpreter) ExitSubtract(ctx *parser.SubtractContext) {
@@ -209,15 +209,15 @@ func (b *bricksInterpreter) ExitMax(ctx *parser.MaxContext) {
209209
log.Printf("Calculating maximum")
210210

211211
max := model.NewCollection()
212-
for range ctx.AllCollectionExp() {
212+
for range ctx.AllCollectionOrId() {
213213
value := b.stack.pop()
214214
if collection, ok := value.(model.Collection); ok {
215215
max.Max(&collection)
216216
} else {
217217
log.Fatal("Only collections can be compared")
218218
}
219219

220-
b.stack.push(max)
220+
b.stack.push(*max)
221221
}
222222
}
223223

scripting/parser/Bricks.g4

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,22 @@ bricks: command+;
44

55
command: assignment | save | export | print | pause;
66

7-
assignment: ID ':=' collectionExp;
7+
expression: collection | build | identifier;
88

9-
save: 'save' '(' (collectionExp | buildExp) ',' STRING ')';
9+
assignment: ID ':=' expression;
1010

11-
export: 'export' '(' (collectionExp | buildExp) ',' STRING ')';
11+
save: 'save' '(' expression ',' STRING ')';
1212

13-
print: 'print' '(' (collectionExp | buildExp) ')';
13+
export: 'export' '(' expression ',' STRING ')';
14+
15+
print: 'print' '(' expression ')';
1416

1517
pause: 'pause' '(' seconds=INT ')';
1618

1719

18-
collectionExp: identifier | load | import_ | allParts | lost | set | userSet | setList | partList | partLists | sum | subtract | max | sort;
20+
collectionOrId: collection | identifier;
21+
22+
collection: load | import_ | allParts | lost | set | userSet | setList | partList | partLists | sum | subtract | max | sort;
1923

2024
load: 'load' '(' STRING ')';
2125

@@ -35,18 +39,16 @@ partList: 'partList' '(' INT ')';
3539

3640
partLists: 'partLists' '(' STRING (',' BOOL)? ')';
3741

38-
sum: 'sum' '(' collectionExp (',' collectionExp)+ ')';
39-
40-
subtract: 'subtract' '(' collectionExp ',' collectionExp ')';
42+
sum: 'sum' '(' collectionOrId (',' collectionOrId)+ ')';
4143

42-
max: 'max' '(' collectionExp (',' collectionExp)+ ')';
44+
subtract: 'subtract' '(' collectionOrId ',' collectionOrId ')';
4345

44-
sort: 'sort' '(' collectionExp (',' quantity='quantity')? (',' descending='descending')? ')';
46+
max: 'max' '(' collectionOrId (',' collectionOrId)+ ')';
4547

48+
sort: 'sort' '(' collectionOrId (',' quantity='quantity')? (',' descending='descending')? ')';
4649

47-
buildExp : identifier | build;
4850

49-
build: 'build' '(' collectionExp ',' collectionExp (',' build_mode=ID )? ')';
51+
build: 'build' '(' collectionOrId ',' collectionOrId (',' build_mode=ID )? ')';
5052

5153

5254
ID: [a-zA-Z][a-zA-Z0-9_]*;

scripting/parser/bricks_base_listener.go

Lines changed: 16 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripting/parser/bricks_listener.go

Lines changed: 16 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)