stupidedi 1.2.20 → 1.3.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +15 -1
- data/bin/edi-obfuscate +112 -0
- data/lib/stupidedi/builder/generation.rb +39 -11
- data/lib/stupidedi/builder/navigation.rb +15 -2
- data/lib/stupidedi/either.rb +1 -1
- data/lib/stupidedi/reader/tokens/component_element_tok.rb +12 -0
- data/lib/stupidedi/reader/tokens/composite_element_tok.rb +17 -0
- data/lib/stupidedi/reader/tokens/segment_tok.rb +19 -1
- data/lib/stupidedi/reader/tokens/simple_element_tok.rb +12 -0
- data/lib/stupidedi/values/functional_group_val.rb +1 -1
- data/lib/stupidedi/values/interchange_val.rb +1 -1
- data/lib/stupidedi/values/loop_val.rb +1 -1
- data/lib/stupidedi/values/table_val.rb +1 -1
- data/lib/stupidedi/values/transaction_set_val.rb +1 -1
- data/lib/stupidedi/values/transmission_val.rb +1 -1
- data/lib/stupidedi/version.rb +1 -1
- data/lib/stupidedi/versions/functional_groups/002001/element_defs.rb +1 -14
- data/lib/stupidedi/versions/functional_groups/002001/element_types/date_val.rb +3 -3
- data/lib/stupidedi/versions/functional_groups/002001/element_types/fixnum_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/002001/element_types/float_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/002001/element_types/identifier_val.rb +1 -1
- data/lib/stupidedi/versions/functional_groups/002001/element_types/string_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/002001/element_types/time_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003010/element_defs.rb +1 -14
- data/lib/stupidedi/versions/functional_groups/003010/element_types/date_val.rb +3 -3
- data/lib/stupidedi/versions/functional_groups/003010/element_types/fixnum_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003010/element_types/float_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003010/element_types/identifier_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003010/element_types/string_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003010/element_types/time_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003040/element_defs.rb +1 -14
- data/lib/stupidedi/versions/functional_groups/003040/element_types/date_val.rb +3 -3
- data/lib/stupidedi/versions/functional_groups/003040/element_types/fixnum_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003040/element_types/float_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003040/element_types/identifier_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003040/element_types/string_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003040/element_types/time_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003050/element_defs.rb +1 -14
- data/lib/stupidedi/versions/functional_groups/003050/element_types/date_val.rb +3 -3
- data/lib/stupidedi/versions/functional_groups/003050/element_types/fixnum_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003050/element_types/float_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003050/element_types/identifier_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003050/element_types/string_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/003050/element_types/time_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/004010/element_defs.rb +2 -3
- data/lib/stupidedi/versions/functional_groups/004010/element_types/date_val.rb +3 -3
- data/lib/stupidedi/versions/functional_groups/004010/element_types/fixnum_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/004010/element_types/float_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/004010/element_types/string_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/004010/element_types/time_val.rb +2 -2
- data/lib/stupidedi/versions/functional_groups/005010/element_types/date_val.rb +1 -1
- data/lib/stupidedi/versions/functional_groups/005010/element_types/fixnum_val.rb +1 -1
- data/lib/stupidedi/versions/functional_groups/005010/element_types/float_val.rb +1 -1
- data/lib/stupidedi/versions/functional_groups/005010/element_types/string_val.rb +1 -1
- data/lib/stupidedi/versions/functional_groups/005010/element_types/time_val.rb +1 -1
- data/lib/stupidedi/versions/interchanges/00200/element_defs.rb +1 -1
- data/lib/stupidedi/versions/interchanges/00300/element_defs.rb +1 -1
- data/lib/stupidedi/versions/interchanges/00400/element_defs.rb +1 -1
- data/lib/stupidedi/versions/interchanges/00401/element_defs.rb +1 -1
- data/spec/examples/integration/navigating_spec.rb +44 -0
- data/spec/examples/integration/nondeterminism_spec.rb +165 -0
- metadata +4 -2
|
@@ -98,7 +98,7 @@ module Stupidedi
|
|
|
98
98
|
|
|
99
99
|
def inspect
|
|
100
100
|
id = definition.try{|d| ansi.bold("[#{d.id}]") }
|
|
101
|
-
ansi.element("SeparatorElementVal.value#{id}")
|
|
101
|
+
ansi.element("SeparatorElementVal.value#{id}") + "(#{@value || "nil"})"
|
|
102
102
|
end
|
|
103
103
|
end
|
|
104
104
|
|
|
@@ -98,7 +98,7 @@ module Stupidedi
|
|
|
98
98
|
|
|
99
99
|
def inspect
|
|
100
100
|
id = definition.try{|d| ansi.bold("[#{d.id}]") }
|
|
101
|
-
ansi.element("SeparatorElementVal.value#{id}")
|
|
101
|
+
ansi.element("SeparatorElementVal.value#{id}") + "(#{@value || "nil"})"
|
|
102
102
|
end
|
|
103
103
|
end
|
|
104
104
|
|
|
@@ -98,7 +98,7 @@ module Stupidedi
|
|
|
98
98
|
|
|
99
99
|
def inspect
|
|
100
100
|
id = definition.try{|d| ansi.bold("[#{d.id}]") }
|
|
101
|
-
ansi.element("SeparatorElementVal.value#{id}")
|
|
101
|
+
ansi.element("SeparatorElementVal.value#{id}") + "(#{@value || "nil"})"
|
|
102
102
|
end
|
|
103
103
|
end
|
|
104
104
|
|
|
@@ -99,7 +99,7 @@ module Stupidedi
|
|
|
99
99
|
|
|
100
100
|
def inspect
|
|
101
101
|
id = definition.try{|d| ansi.bold("[#{d.id}]") }
|
|
102
|
-
ansi.element("SeparatorElementVal.value#{id}")
|
|
102
|
+
ansi.element("SeparatorElementVal.value#{id}") + "(#{@value || "nil"})"
|
|
103
103
|
end
|
|
104
104
|
end
|
|
105
105
|
|
|
@@ -49,6 +49,50 @@ describe "Navigating" do
|
|
|
49
49
|
end
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
+
context "repeatable segments" do
|
|
53
|
+
specify "can be iterated" do
|
|
54
|
+
expect(lambda do
|
|
55
|
+
payment.flatmap do |m|
|
|
56
|
+
m.iterate(:ISA) do |isa|
|
|
57
|
+
raise "didn't expect a second ISA segment"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end).not_to raise_error
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
specify "can be iterated" do
|
|
64
|
+
expect(lambda do
|
|
65
|
+
payment.flatmap do |m|
|
|
66
|
+
m.iterate(:GS) do |gs|
|
|
67
|
+
expect(gs.segment.tap do |segment|
|
|
68
|
+
expect(segment.node.id).to eq(:GS)
|
|
69
|
+
end).to be_defined
|
|
70
|
+
|
|
71
|
+
gs.iterate(:ST) do |st|
|
|
72
|
+
expect(st.segment.tap do |segment|
|
|
73
|
+
expect(segment.node.id).to eq(:ST)
|
|
74
|
+
end).to be_defined
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end).not_to raise_error
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
context "non-repeatable segments" do
|
|
83
|
+
specify "cannot be iterated" do
|
|
84
|
+
expect(lambda do
|
|
85
|
+
payment.flatmap do |m|
|
|
86
|
+
m.iterate(:GS) do |gs|
|
|
87
|
+
gs.iterate(:ST) do |st|
|
|
88
|
+
st.iterate(:BHT)
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end).to raise_error("BHT segment is not repeatable")
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
52
96
|
describe "error handling" do
|
|
53
97
|
context "accessing an undefined element" do
|
|
54
98
|
it "raises an exception" do
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
require "spec_helper"
|
|
2
|
+
require "pp"
|
|
3
|
+
|
|
4
|
+
describe "Non-determinism" do
|
|
5
|
+
include NavigationMatchers
|
|
6
|
+
|
|
7
|
+
let(:strict) { Stupidedi::Builder::BuilderDsl.build(config, true) }
|
|
8
|
+
let(:relaxed) { Stupidedi::Builder::BuilderDsl.build(config, false) }
|
|
9
|
+
|
|
10
|
+
let(:config) do
|
|
11
|
+
Stupidedi::Config.default.customize do |c|
|
|
12
|
+
c.transaction_set.customize do |x|
|
|
13
|
+
x.register("005010", "BE", "999") { schema }
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
let(:schema) do
|
|
19
|
+
d = Stupidedi::Schema
|
|
20
|
+
r = Stupidedi::Versions::FunctionalGroups::FiftyTen::SegmentReqs
|
|
21
|
+
s = Stupidedi::Versions::FunctionalGroups::FiftyTen::SegmentDefs
|
|
22
|
+
|
|
23
|
+
d::TransactionSetDef.build("BE", "000", "Example of Ambiguous Grammar",
|
|
24
|
+
d::TableDef.header("Table 1",
|
|
25
|
+
s::ST.use(10, r::Mandatory, d::RepeatCount.bounded(1))),
|
|
26
|
+
d::TableDef.detail("Table 2",
|
|
27
|
+
d::LoopDef.build("Loop 1", d::RepeatCount.bounded(1),
|
|
28
|
+
s::N1.use(20, r::Mandatory, d::RepeatCount.bounded(1)),
|
|
29
|
+
s::N3.use(30, r::Optional, d::RepeatCount.bounded(1))),
|
|
30
|
+
d::LoopDef.build("Loop 2", d::RepeatCount.bounded(1),
|
|
31
|
+
s::N1.use(40, r::Mandatory, d::RepeatCount.bounded(1)),
|
|
32
|
+
s::N4.use(50, r::Optional, d::RepeatCount.bounded(1)))),
|
|
33
|
+
d::TableDef.summary("Table 3",
|
|
34
|
+
s::SE.use(60, r::Mandatory, d::RepeatCount.bounded(1))))
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
let(:nondet_zero) { Fixtures.parse_("GH-129/1.txt") }
|
|
38
|
+
let(:nondet_five) { Fixtures.parse_("GH-129/1.txt") }
|
|
39
|
+
let(:nondet_nine) { Fixtures.parse_("GH-129/1.txt") }
|
|
40
|
+
|
|
41
|
+
def prelude(dsl)
|
|
42
|
+
dsl.ISA("00", "", "00", "", "ZZ", "_", "ZZ", "_",
|
|
43
|
+
Time.now.utc, Time.now.utc, "", "00501",
|
|
44
|
+
123456789, "1", "T", "")
|
|
45
|
+
|
|
46
|
+
dsl.GS("BE", "SENDER ID", "RECEIVER ID",
|
|
47
|
+
Time.now.utc, Time.now.utc, "1", "X", "005010")
|
|
48
|
+
|
|
49
|
+
dsl.ST("999", "0000", "005010")
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
context "generating an ambiguous segment" do
|
|
53
|
+
context "when strict" do
|
|
54
|
+
it "throws an exception" do
|
|
55
|
+
expect(lambda do
|
|
56
|
+
prelude(strict)
|
|
57
|
+
.N1("6Y", "BOB BELCHER")
|
|
58
|
+
.N1("6Y", "NON DETERMINISM") # could be Loop 1 or Loop 2
|
|
59
|
+
end).to raise_error \
|
|
60
|
+
"non-deterministic machine state: N1 Party Identification, N1 Party Identification"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
context "when non-strict" do
|
|
65
|
+
it "does not throw an exception" do
|
|
66
|
+
expect(lambda do
|
|
67
|
+
prelude(relaxed)
|
|
68
|
+
.N1("6Y", "BOB BELCHER")
|
|
69
|
+
.N1("6Y", "NON DETERMINISM") # could be Loop 1 or Loop 2
|
|
70
|
+
end).not_to raise_error
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
context "with later unambiguous input" do
|
|
74
|
+
it "does not discard invalid trees" do
|
|
75
|
+
expect(prelude(relaxed)
|
|
76
|
+
.N1("6Y", "BOB BELCHER")
|
|
77
|
+
.N1("6Y", "NON DETERMINISM") # could be Loop 1 or Loop 2
|
|
78
|
+
.N3("OCEAN AVENUE") # could only be Loop 1
|
|
79
|
+
.machine.active.length
|
|
80
|
+
).to eq(2)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "does not discard invalid trees" do
|
|
84
|
+
expect(prelude(relaxed)
|
|
85
|
+
.N1("6Y", "BOB BELCHER")
|
|
86
|
+
.N1("6Y", "NON DETERMINISM") # could be Loop 1 or Loop 2
|
|
87
|
+
.N4("UNKNOWN CITY") # could only be Loop 2
|
|
88
|
+
.machine.active.length
|
|
89
|
+
).to eq(2)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
context "reading" do
|
|
96
|
+
def read(suffix, nondeterminism: 1)
|
|
97
|
+
input =
|
|
98
|
+
["ISA*00*..........*01*SECRET....*ZZ*SUBMITTERS.ID..*ZZ*RECEIVERS.ID...*030101*1253*^*00501*000000905*1*T*:~",
|
|
99
|
+
"GS*BE*SENDER ID*RECEIVER ID*19991231*0802*1*x*005010~",
|
|
100
|
+
"ST*999*0000*005010~",
|
|
101
|
+
"N1*6Y*LINDA BELCHER~",
|
|
102
|
+
suffix].join("\n")
|
|
103
|
+
|
|
104
|
+
machine = Stupidedi::Builder::StateMachine.build(config)
|
|
105
|
+
machine.read(Stupidedi::Reader.build(input), nondeterminism: nondeterminism)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
context "when nondenterminism = 1" do
|
|
109
|
+
it "ordinary input suceeds" do
|
|
110
|
+
machine, result = read("N3*OCEAN AVENUE~", nondeterminism: 1)
|
|
111
|
+
|
|
112
|
+
result.should_not be_fatal
|
|
113
|
+
result.reason.should eq("reached end of input without finding a segment identifier")
|
|
114
|
+
machine.should be_deterministic
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
it "ambiguous input causes a failure result" do
|
|
118
|
+
machine, result = read("N1*6Y*NON DETERMINISM~...", nondeterminism: 1)
|
|
119
|
+
|
|
120
|
+
result.should be_fatal # no usable parse tree
|
|
121
|
+
result.reason.should eq("too much non-determinism: N1 Party Identification, N1 Party Identification")
|
|
122
|
+
result.remainder.should eq("...")
|
|
123
|
+
machine.should_not be_deterministic
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
context "when nondenterminism = 2" do
|
|
128
|
+
it "acceptably ambiguous input succeeds" do
|
|
129
|
+
machine, result = read("N1*6Y*NON DETERMINISM~...", nondeterminism: 2)
|
|
130
|
+
|
|
131
|
+
result.should_not be_fatal # we have a usable parse tree, despite trailing garbage
|
|
132
|
+
result.remainder.should eq("...")
|
|
133
|
+
machine.should_not be_deterministic
|
|
134
|
+
machine.active.length.should eq(2)
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it "too much ambiguity causes a failure" do
|
|
138
|
+
machine, result = read(
|
|
139
|
+
"N1*6Y*NON DETERMINISM~" \
|
|
140
|
+
"N1*6Y*THIS IS TOO MUCH~...", nondeterminism: 2)
|
|
141
|
+
|
|
142
|
+
result.should be_fatal # no useable parse tree
|
|
143
|
+
result.remainder.should eq("...")
|
|
144
|
+
machine.should_not be_deterministic
|
|
145
|
+
machine.active.length.should eq(1 + 2)
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
context "when nondenterminism = 3" do
|
|
150
|
+
it "too much ambiguity causes a failure" do
|
|
151
|
+
machine, result = read(
|
|
152
|
+
"N1*6Y*NON DETERMINISM~" \
|
|
153
|
+
"N1*6Y*BLAH BLAH BLAH~" \
|
|
154
|
+
"N1*6Y*THIS IS TOO MUCH~" \
|
|
155
|
+
"N1*6Y*NOT GONNA SEE THIS~...", nondeterminism: 3)
|
|
156
|
+
|
|
157
|
+
result.should be_fatal # no useable parse tree
|
|
158
|
+
result.remainder.should eq("N1*6Y*NOT GONNA SEE THIS~...")
|
|
159
|
+
machine.should_not be_deterministic
|
|
160
|
+
machine.active.length.should eq(1 + 2*2)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: stupidedi
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.21
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kyle Putnam/Isi Robayna
|
|
@@ -49,6 +49,7 @@ files:
|
|
|
49
49
|
- README.md
|
|
50
50
|
- Rakefile
|
|
51
51
|
- bin/edi-ed
|
|
52
|
+
- bin/edi-obfuscate
|
|
52
53
|
- bin/edi-pp
|
|
53
54
|
- doc/Generating.md
|
|
54
55
|
- doc/Navigating.md
|
|
@@ -973,6 +974,7 @@ files:
|
|
|
973
974
|
- lib/stupidedi/zipper/root_cursor.rb
|
|
974
975
|
- spec/examples/integration/generating_spec.rb
|
|
975
976
|
- spec/examples/integration/navigating_spec.rb
|
|
977
|
+
- spec/examples/integration/nondeterminism_spec.rb
|
|
976
978
|
- spec/examples/integration/parsing/005010/X091A1-HP835_spec.rb
|
|
977
979
|
- spec/examples/integration/parsing/005010/X212-HR276_spec.rb
|
|
978
980
|
- spec/examples/integration/parsing/005010/X221-HP835_spec.rb
|
|
@@ -1211,7 +1213,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
1211
1213
|
version: '0'
|
|
1212
1214
|
requirements: []
|
|
1213
1215
|
rubyforge_project:
|
|
1214
|
-
rubygems_version: 2.7.
|
|
1216
|
+
rubygems_version: 2.7.8
|
|
1215
1217
|
signing_key:
|
|
1216
1218
|
specification_version: 4
|
|
1217
1219
|
summary: Parse, generate, validate ASC X12 EDI
|