Skip to content

Commit fadf70c

Browse files
authored
GH-40 - Fix group/struct delving & recovery (#43)
* Adjust group/struct delving and recovery * Validate final PIC not incl. * Cleanup lint
1 parent 0ed9560 commit fadf70c

File tree

3 files changed

+90
-22
lines changed

3 files changed

+90
-22
lines changed

pkg/lex/parserfn.go

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,11 @@ func parsePIC(_ *Tree, l line, _ *Record) *Record {
2828
}
2929

3030
return &Record{
31-
Name: l.items[4].val,
32-
Length: length,
33-
depth: l.items[2].val,
34-
Typ: parsePICType(picNumDef),
31+
depthMap: map[string]*Record{},
32+
Name: l.items[4].val,
33+
Length: length,
34+
depth: l.items[2].val,
35+
Typ: parsePICType(picNumDef),
3536
}
3637
}
3738

@@ -48,9 +49,10 @@ func parseRedefines(_ *Tree, l line, root *Record) *Record {
4849
}
4950

5051
r := &Record{
51-
Name: l.items[4].val,
52-
Length: length,
53-
Typ: parsePICType(picNumDef),
52+
depthMap: map[string]*Record{},
53+
Name: l.items[4].val,
54+
Length: length,
55+
Typ: parsePICType(picNumDef),
5456
}
5557

5658
target := l.items[8].val
@@ -75,7 +77,7 @@ func parseGroupRedefines(t *Tree, l line, root *Record) *Record {
7577
log.Fatalln(fmt.Sprintf("redefinition target %s does not exist", target))
7678
}
7779

78-
if dst.depthMap == nil {
80+
if dst.depthMap == nil || len(dst.depthMap) == 0 {
7981
// then check whether a node has children at this depth
8082
parent, seenGroup := root.depthMap[dst.depth]
8183
if seenGroup {
@@ -116,11 +118,12 @@ func parseOccurs(_ *Tree, l line, _ *Record) *Record {
116118
}
117119

118120
return &Record{
119-
Name: l.items[4].val,
120-
Length: length,
121-
Occurs: n,
122-
depth: l.items[2].val,
123-
Typ: parsePICType(picNumDef),
121+
Name: l.items[4].val,
122+
Length: length,
123+
Occurs: n,
124+
depth: l.items[2].val,
125+
depthMap: map[string]*Record{},
126+
Typ: parsePICType(picNumDef),
124127
}
125128
}
126129

@@ -212,20 +215,24 @@ func parseNonNumDelimitedStruct(t *Tree, l line, root *Record) *Record {
212215
// | |-picA
213216
// |-group2
214217
// | |-picA
215-
func parseStruct(t *Tree, l line, root *Record, nameIdx, groupIdx int) *Record {
218+
func parseStruct(_ *Tree, l line, _ *Record, nameIdx, groupIdx int) *Record {
216219
newNode := &Record{
217-
Name: l.items[nameIdx].val,
218-
Typ: reflect.Struct,
219-
depth: l.items[groupIdx].val,
220+
Name: l.items[nameIdx].val,
221+
Typ: reflect.Struct,
222+
depth: l.items[groupIdx].val,
223+
depthMap: map[string]*Record{},
220224
}
221225

222-
return delve(t, root, newNode)
226+
return newNode
223227
}
224228

225229
func delve(t *Tree, root *Record, newRecord *Record) *Record {
226230
parent, seenGroup := root.depthMap[newRecord.depth]
227231
if seenGroup {
228232
parent.Children = append(parent.Children, newRecord)
233+
if newRecord.depthMap == nil || len(newRecord.depthMap) == 0 {
234+
copyDepthMap(parent, newRecord)
235+
}
229236
t.parseLines(newRecord)
230237
l := newRecord.Length
231238
if newRecord.Occurs > 0 {
@@ -237,7 +244,7 @@ func delve(t *Tree, root *Record, newRecord *Record) *Record {
237244
return parent
238245
}
239246

240-
if root.depthMap == nil {
247+
if root.depthMap == nil || len(root.depthMap) == 0 {
241248
root.depthMap = make(map[string]*Record)
242249
}
243250

@@ -258,7 +265,7 @@ func delve(t *Tree, root *Record, newRecord *Record) *Record {
258265
}
259266

260267
func copyDepthMap(src, dst *Record) {
261-
if dst.depthMap == nil {
268+
if dst.depthMap == nil || len(dst.depthMap) == 0 {
262269
dst.depthMap = make(map[string]*Record)
263270
}
264271

pkg/lex/tree.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func (t *Tree) next() item {
7373

7474
// parseLines generates the text for the line
7575
// and adds it to the tree data
76-
func (t *Tree) parseLines(root *Record) {
76+
func (t *Tree) parseLines(root *Record) { //nolint:gocyclo // TODO: refine
7777
for {
7878
if errors.Is(t.nextLine(), io.EOF) {
7979
break
@@ -84,9 +84,22 @@ func (t *Tree) parseLines(root *Record) {
8484
log.Printf("%s on copybook line %d resulted in no-op", t.line.typ, t.lIdx)
8585
continue
8686

87-
case lineStruct, lineRedefines, lineGroupRedefines, lineMultilineRedefines:
87+
case lineRedefines, lineMultilineRedefines, lineGroupRedefines:
8888
t.line.fn(t, t.line, root)
8989

90+
case lineStruct:
91+
rec := t.line.fn(t, t.line, root)
92+
if rec == nil {
93+
continue
94+
}
95+
96+
parent, ok := root.depthMap[rec.depth]
97+
if ok {
98+
root = parent
99+
}
100+
101+
delve(t, root, rec)
102+
90103
default:
91104
rec := t.line.fn(t, t.line, root)
92105
if rec == nil {

pkg/lex/tree_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,54 @@ func Test_Parse(t *testing.T) {
431431
},
432432
},
433433
},
434+
}, {
435+
name: "ValidateGrouping",
436+
in: NewTree(
437+
New("test",
438+
`000160 05 DUMMY-GROUP-1. 00000115
439+
000170 10 DUMMY-SUB-GROUP-1. 00000116
440+
000180 15 DUMMY-GROUP-1-OBJECT-A PIC 9(9).9(2). 00000117
441+
000190 15 DUMMY-GROUP-1-OBJECT-B PIC X. 00000118
442+
000200 15 DUMMY-GROUP-1-OBJECT-C PIC 9(4).9(4). 00000119
443+
000210 10 DUMMY-OBJECT-A PIC X. 00000120
444+
`)),
445+
want: &Record{
446+
Name: "test",
447+
Typ: reflect.Struct,
448+
Length: 23,
449+
Children: []*Record{
450+
{
451+
Name: "DUMMY-GROUP-1",
452+
Typ: reflect.Struct,
453+
Length: 23,
454+
Children: []*Record{
455+
{
456+
Name: "DUMMY-SUB-GROUP-1",
457+
Typ: reflect.Struct,
458+
Length: 22,
459+
Children: []*Record{{
460+
Name: "DUMMY-GROUP-1-OBJECT-A",
461+
Typ: reflect.Float64,
462+
Length: 12,
463+
}, {
464+
Name: "DUMMY-GROUP-1-OBJECT-B",
465+
Typ: reflect.String,
466+
Length: 1,
467+
}, {
468+
Name: "DUMMY-GROUP-1-OBJECT-C",
469+
Typ: reflect.Float64,
470+
Length: 9,
471+
},
472+
},
473+
}, {
474+
Name: "DUMMY-OBJECT-A",
475+
Length: 1,
476+
Typ: reflect.String,
477+
},
478+
},
479+
},
480+
},
481+
},
434482
},
435483
}
436484

0 commit comments

Comments
 (0)