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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: dca3cbe38e197d5e24eb127bb9ea501a7417e8ebdef6ce29c0841cd8a7f618f8
|
|
4
|
+
data.tar.gz: d7d967d793ee60bed8b4f4794f1168a102c07369db5deb1814727ff14d6a4b4e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 075d7961db6721b5e60125c7a1fc98e58ed1a2847c55dce06c9ff138a0a0d745a95ca0d798e6c38923fbdfa250b60b6c026a4242fe308d7df170385b3b44ef9c
|
|
7
|
+
data.tar.gz: a899f00431881d6edd7cbf083c551f70af676bff1cc9b21df8dcbd9bc41723bf8dab402484f3a028b79b05c7abcbec745c3b95dd854c10a0c9337d62e03eb632
|
data/README.md
CHANGED
|
@@ -233,6 +233,8 @@ Perform validation on a file
|
|
|
233
233
|
|
|
234
234
|
### Generating, Writing
|
|
235
235
|
|
|
236
|
+
#### X12 Writer
|
|
237
|
+
|
|
236
238
|
```ruby
|
|
237
239
|
require "stupidedi"
|
|
238
240
|
|
|
@@ -301,7 +303,9 @@ b.machine.zipper.tap do |z|
|
|
|
301
303
|
end
|
|
302
304
|
```
|
|
303
305
|
|
|
304
|
-
|
|
306
|
+
#### HTML writer
|
|
307
|
+
|
|
308
|
+
As shown above `Stupidedi::Writer::Default` will output data encoded in plain x12 format. While `Stupidedi::Writer::Claredi` will output a formatted HTML string.
|
|
305
309
|
|
|
306
310
|
`Stupidedi::Writer::Claredi#write` operates on `StringIO`.
|
|
307
311
|
|
|
@@ -313,6 +317,16 @@ b.machine.zipper.tap do |z|
|
|
|
313
317
|
end
|
|
314
318
|
```
|
|
315
319
|
|
|
320
|
+
#### Json (Hash) Writer
|
|
321
|
+
|
|
322
|
+
Converting the tree to a JSON document is intentionally not included in the library. However this still may be implemented utilizing the stupidedi API.
|
|
323
|
+
|
|
324
|
+
[Here](https://github.com/irobayna/stupidedi/blob/master/notes/json_writer/json.rb) is one of the possible ways to implement this.
|
|
325
|
+
|
|
326
|
+
The shown approach allows to define custom traversing logic for the nodes with ability to change hash keys and values to whatever is needed.
|
|
327
|
+
|
|
328
|
+
Please refer to [this readme](https://github.com/irobayna/stupidedi/blob/master/notes/json_writer/json.MD) and [these nodes implementation](https://github.com/irobayna/stupidedi/blob/master/notes/json_writer/json/) for more information.
|
|
329
|
+
|
|
316
330
|
### Reading, Traversing
|
|
317
331
|
|
|
318
332
|
```ruby
|
data/bin/edi-obfuscate
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
#
|
|
3
|
+
# This is a utility that will strip all free-form text (elements of type AN),
|
|
4
|
+
# dates, and times from an X12 file. Strings are replaced with underscores,
|
|
5
|
+
# dates are replaced with 2015-12-30, and times are replaced with 00:00:00.
|
|
6
|
+
#
|
|
7
|
+
# When -s is given, then unrecognized elements and segments will be suppressed
|
|
8
|
+
# from the output.
|
|
9
|
+
#
|
|
10
|
+
# Otherwise, unrecognized segments or elements will cause an exception since it
|
|
11
|
+
# is not possible to know if these should be obfuscated or not (they are invalid).
|
|
12
|
+
#
|
|
13
|
+
require File.expand_path("../../lib/stupidedi", __FILE__)
|
|
14
|
+
|
|
15
|
+
require "stupidedi"
|
|
16
|
+
require "pp"
|
|
17
|
+
|
|
18
|
+
# Short-lived processes should win some peformance gains here
|
|
19
|
+
GC.disable
|
|
20
|
+
|
|
21
|
+
def main(argv)
|
|
22
|
+
strict = !argv.delete("-s")
|
|
23
|
+
config = Stupidedi::Config.default
|
|
24
|
+
reader = Stupidedi::Reader.build(File.open(argv[0]))
|
|
25
|
+
|
|
26
|
+
# First segment (ISA) specifies separators, used for parsing
|
|
27
|
+
result = reader.read_segment
|
|
28
|
+
|
|
29
|
+
result.tap do
|
|
30
|
+
lookup = result.remainder.segment_dict.push(
|
|
31
|
+
config.interchange.at(result.fetch.element_toks[11].value).segment_dict)
|
|
32
|
+
|
|
33
|
+
reader = result.remainder.copy(segment_dict: lookup)
|
|
34
|
+
delims = result.remainder.separators.copy(component: result.fetch.element_toks[15].value)
|
|
35
|
+
reader = reader.copy(separators: delims)
|
|
36
|
+
|
|
37
|
+
while result.defined?
|
|
38
|
+
result.tap do |token|
|
|
39
|
+
if token.id == :GS
|
|
40
|
+
gs08 = result.fetch.element_toks[7].value.slice(0, 6)
|
|
41
|
+
lookup = lookup.push(config.functional_group.at(gs08).segment_dict)
|
|
42
|
+
reader = reader.copy(segment_dict: lookup)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
if lookup.defined_at?(token.id)
|
|
46
|
+
segment_def = lookup.at(token.id)
|
|
47
|
+
element_toks = token.element_toks.zip(segment_def.element_uses).map.each_with_index do |(e, u), n|
|
|
48
|
+
if u.nil?
|
|
49
|
+
raise "unrecognized element: #{token.id}-#{"%02d" % n}" if strict
|
|
50
|
+
|
|
51
|
+
# This won't terminate the inner loop immediately, but if this
|
|
52
|
+
# element is unknown, it's because there were too many elements
|
|
53
|
+
# for the given segment. So all the extra elements at the end
|
|
54
|
+
# will still be skipped
|
|
55
|
+
next
|
|
56
|
+
elsif u.simple?
|
|
57
|
+
simple(e, u)
|
|
58
|
+
else
|
|
59
|
+
composite(e, u)
|
|
60
|
+
end
|
|
61
|
+
end.compact
|
|
62
|
+
|
|
63
|
+
puts token.copy(element_toks: element_toks).to_s(delims)
|
|
64
|
+
else
|
|
65
|
+
raise "unknown segment: #{token.id}" if strict
|
|
66
|
+
next
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
result = reader.read_segment
|
|
71
|
+
reader = result.remainder
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
result.explain{|msg| raise msg } if result.fatal?
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def simple(e, u)
|
|
79
|
+
type = u.definition.class.name
|
|
80
|
+
type = (type || "?").split("::").last
|
|
81
|
+
|
|
82
|
+
# GS-08 and ST-03 are preserved, since these have special meaning to the parser
|
|
83
|
+
if e.blank? or [:E1705, :E480].include?(u.definition.id)
|
|
84
|
+
return e
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
if type.end_with?("AN")
|
|
88
|
+
e.copy(value: "_" * u.definition.min_length)
|
|
89
|
+
elsif type == "TM"
|
|
90
|
+
e.copy(value: "0" * e.value.length)
|
|
91
|
+
elsif type == "DT"
|
|
92
|
+
if e.value.length == 8
|
|
93
|
+
e.copy(value: "20151230")
|
|
94
|
+
else
|
|
95
|
+
e.copy(value: "151230")
|
|
96
|
+
end
|
|
97
|
+
else
|
|
98
|
+
e
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def composite(e, u)
|
|
103
|
+
component_toks = []
|
|
104
|
+
|
|
105
|
+
e.component_toks.zip(u.definition.component_uses) do |ce, cu|
|
|
106
|
+
component_toks.push(simple(ce, cu))
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
e.copy(component_toks: component_toks)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
main(ARGV)
|
|
@@ -7,21 +7,49 @@ module Stupidedi
|
|
|
7
7
|
|
|
8
8
|
module Generation
|
|
9
9
|
|
|
10
|
-
#
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
# Consumes all input from `reader` and returns the updated
|
|
11
|
+
# {StateMachine} along with the result of the last attempt
|
|
12
|
+
# to read a segment.
|
|
13
|
+
#
|
|
14
|
+
# The `nondeterminism` argument specifies a limit on how many
|
|
15
|
+
# parse trees can be built simultaneously due to ambiguity in
|
|
16
|
+
# the input and/or specification. This prevents runaway memory
|
|
17
|
+
# CPU consumption (see GH-129), and will return a {Result.failure}
|
|
18
|
+
# once exceeded.
|
|
19
|
+
#
|
|
20
|
+
# The default value is 1, resulting in an error if any input
|
|
21
|
+
# is ambiguous.
|
|
22
|
+
#
|
|
23
|
+
# NOTE: The error is detected *after* the resources are already
|
|
24
|
+
# been consumed. The extra parse trees are returned (in memory)
|
|
25
|
+
# via the {StateMachine} to aide diagnosis.
|
|
26
|
+
#
|
|
27
|
+
# @return [(StateMachine, Reader::Result)]
|
|
28
|
+
def read(reader, options = {})
|
|
29
|
+
limit = options.fetch(:nondeterminism, 1)
|
|
30
|
+
machine = self
|
|
31
|
+
reader_e = reader.read_segment
|
|
32
|
+
|
|
33
|
+
while reader_e.defined?
|
|
34
|
+
reader_e = reader_e.flatmap do |segment_tok, reader|
|
|
35
|
+
machine, reader_ =
|
|
36
|
+
machine.insert(segment_tok, reader)
|
|
37
|
+
|
|
38
|
+
if machine.active.length <= limit
|
|
39
|
+
reader_.read_segment
|
|
40
|
+
else
|
|
41
|
+
matches = machine.active.map do |m|
|
|
42
|
+
segment_def = m.node.zipper.node.definition
|
|
43
|
+
"#{segment_def.id} #{segment_def.name}"
|
|
44
|
+
end.join(", ")
|
|
19
45
|
|
|
20
|
-
|
|
46
|
+
return machine,
|
|
47
|
+
Reader::Result.failure("too much non-determinism: #{matches}", reader_.input, true)
|
|
48
|
+
end
|
|
21
49
|
end
|
|
22
50
|
end
|
|
23
51
|
|
|
24
|
-
return machine,
|
|
52
|
+
return machine, reader_e
|
|
25
53
|
end
|
|
26
54
|
|
|
27
55
|
# @return [(StateMachine, Reader::TokenReader)]
|
|
@@ -453,7 +453,7 @@ module Stupidedi
|
|
|
453
453
|
# @return [Either<Array<Object>>]
|
|
454
454
|
def iterate(id, *elements)
|
|
455
455
|
a = []
|
|
456
|
-
m =
|
|
456
|
+
m = __find(false, id, elements, true)
|
|
457
457
|
return m unless m.defined?
|
|
458
458
|
|
|
459
459
|
while m.defined?
|
|
@@ -485,10 +485,16 @@ module Stupidedi
|
|
|
485
485
|
private
|
|
486
486
|
|
|
487
487
|
# @return [Either<StateMachine>]
|
|
488
|
-
def __find(invalid, id, elements)
|
|
488
|
+
def __find(invalid, id, elements, assert_repeatable = false)
|
|
489
489
|
reachable = false
|
|
490
490
|
matches = []
|
|
491
491
|
|
|
492
|
+
# Note op.segment_use.nil? is true when searching for ISA,
|
|
493
|
+
# GS, and ST, because we can't know the SegmentUse until we
|
|
494
|
+
# deconstruct the token and looked up the versions numbers
|
|
495
|
+
# in the Config. Nonetheless, we know ISA, GS, and ST can repeat
|
|
496
|
+
repeatable = [:ISA, :GS, :ST].include?(id)
|
|
497
|
+
|
|
492
498
|
@active.each do |zipper|
|
|
493
499
|
matched = false
|
|
494
500
|
filter_tok = mksegment_tok(zipper.node.segment_dict, id, elements, nil)
|
|
@@ -515,6 +521,8 @@ module Stupidedi
|
|
|
515
521
|
state = zipper
|
|
516
522
|
value = zipper.node.zipper
|
|
517
523
|
|
|
524
|
+
repeatable ||= op_.segment_use.try(:repeatable?)
|
|
525
|
+
|
|
518
526
|
# 1. Move upward (possibly zero times)
|
|
519
527
|
op_.pop_count.times do
|
|
520
528
|
value = value.up
|
|
@@ -625,6 +633,11 @@ module Stupidedi
|
|
|
625
633
|
end
|
|
626
634
|
end
|
|
627
635
|
|
|
636
|
+
if assert_repeatable and not repeatable
|
|
637
|
+
raise Exceptions::ParseError,
|
|
638
|
+
"#{id} segment is not repeatable"
|
|
639
|
+
end
|
|
640
|
+
|
|
628
641
|
if not reachable
|
|
629
642
|
raise Exceptions::ParseError,
|
|
630
643
|
"#{id} segment cannot be reached from the current state"
|
data/lib/stupidedi/either.rb
CHANGED
|
@@ -21,6 +21,14 @@ module Stupidedi
|
|
|
21
21
|
value, position, remainder
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
# @return [CompositeElementTok]
|
|
25
|
+
def copy(changes = {})
|
|
26
|
+
ComponentElementTok.new \
|
|
27
|
+
changes.fetch(:value, @value),
|
|
28
|
+
changes.fetch(:position, @position),
|
|
29
|
+
changes.fetch(:remainder, @remainder)
|
|
30
|
+
end
|
|
31
|
+
|
|
24
32
|
def pretty_print(q)
|
|
25
33
|
q.pp(:component.cons(@value.cons))
|
|
26
34
|
end
|
|
@@ -40,6 +48,10 @@ module Stupidedi
|
|
|
40
48
|
def composite?
|
|
41
49
|
false
|
|
42
50
|
end
|
|
51
|
+
|
|
52
|
+
def to_s(separators)
|
|
53
|
+
@value
|
|
54
|
+
end
|
|
43
55
|
end
|
|
44
56
|
|
|
45
57
|
class << ComponentElementTok
|
|
@@ -21,6 +21,14 @@ module Stupidedi
|
|
|
21
21
|
component_toks, position, remainder
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
# @return [CompositeElementTok]
|
|
25
|
+
def copy(changes = {})
|
|
26
|
+
CompositeElementTok.new \
|
|
27
|
+
changes.fetch(:component_toks, @component_toks),
|
|
28
|
+
changes.fetch(:position, @position),
|
|
29
|
+
changes.fetch(:remainder, @remainder)
|
|
30
|
+
end
|
|
31
|
+
|
|
24
32
|
def pretty_print(q)
|
|
25
33
|
q.pp(:composite.cons(@component_toks))
|
|
26
34
|
end
|
|
@@ -48,6 +56,15 @@ module Stupidedi
|
|
|
48
56
|
def composite?
|
|
49
57
|
true
|
|
50
58
|
end
|
|
59
|
+
|
|
60
|
+
def to_s(separators)
|
|
61
|
+
if blank?
|
|
62
|
+
""
|
|
63
|
+
else
|
|
64
|
+
cs = @component_toks.map{|x| x.to_s(separators) }
|
|
65
|
+
cs.join(separators.component)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
51
68
|
end
|
|
52
69
|
|
|
53
70
|
class << CompositeElementTok
|
|
@@ -24,17 +24,35 @@ module Stupidedi
|
|
|
24
24
|
id, element_toks, position, remainder
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
+
# @return [SegmentTok]
|
|
28
|
+
def copy(changes = {})
|
|
29
|
+
SegmentTok.new \
|
|
30
|
+
changes.fetch(:id, @id),
|
|
31
|
+
changes.fetch(:element_toks, @element_toks),
|
|
32
|
+
changes.fetch(:position, @position),
|
|
33
|
+
changes.fetch(:remainder, @remainder)
|
|
34
|
+
end
|
|
35
|
+
|
|
27
36
|
def pretty_print(q)
|
|
28
37
|
q.pp(:segment.cons(@id.cons(@element_toks)))
|
|
29
38
|
end
|
|
30
39
|
|
|
31
40
|
def blank?
|
|
32
|
-
@element_toks.all(&:blank?)
|
|
41
|
+
@element_toks.all?(&:blank?)
|
|
33
42
|
end
|
|
34
43
|
|
|
35
44
|
def present?
|
|
36
45
|
not blank?
|
|
37
46
|
end
|
|
47
|
+
|
|
48
|
+
def to_s(separators)
|
|
49
|
+
if blank?
|
|
50
|
+
"#{id}#{separators.segment}"
|
|
51
|
+
else
|
|
52
|
+
es = @element_toks.map{|x| x.to_s(separators) }
|
|
53
|
+
id.cons(es).join(separators.element) + separators.segment
|
|
54
|
+
end
|
|
55
|
+
end
|
|
38
56
|
end
|
|
39
57
|
|
|
40
58
|
class << SegmentTok
|
|
@@ -21,6 +21,14 @@ module Stupidedi
|
|
|
21
21
|
value, position, remainder
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
# @return [SimpleElementTok]
|
|
25
|
+
def copy(changes = {})
|
|
26
|
+
SimpleElementTok.new \
|
|
27
|
+
changes.fetch(:value, @value),
|
|
28
|
+
changes.fetch(:position, @position),
|
|
29
|
+
changes.fetch(:remainder, @remainder)
|
|
30
|
+
end
|
|
31
|
+
|
|
24
32
|
def pretty_print(q)
|
|
25
33
|
q.pp(:simple.cons(@value.cons))
|
|
26
34
|
end
|
|
@@ -48,6 +56,10 @@ module Stupidedi
|
|
|
48
56
|
def composite?
|
|
49
57
|
false
|
|
50
58
|
end
|
|
59
|
+
|
|
60
|
+
def to_s(separators)
|
|
61
|
+
@value
|
|
62
|
+
end
|
|
51
63
|
end
|
|
52
64
|
|
|
53
65
|
class << SimpleElementTok
|