Class: Stupidedi::Parser::BuilderDsl
- Inherits:
-
Object
- Object
- Stupidedi::Parser::BuilderDsl
- Includes:
- Inspect, Tokenization
- Defined in:
- lib/stupidedi/parser/builder_dsl.rb
Instance Attribute Summary collapse
- #machine ⇒ StateMachine readonly
- #reader ⇒ DslReader readonly
- #strict ⇒ Boolean writeonly
Constructors collapse
Instance Method Summary collapse
-
#initialize(machine, strict = true) ⇒ BuilderDsl
constructor
A new instance of BuilderDsl.
- #respond_to_missing?(name, include_private = false) ⇒ Boolean
- #segment!(name, position, *elements) ⇒ BuilderDsl
- #strict? ⇒ Boolean
Methods included from Tokenization
#blank, #composite, #default, #not_used, #repeated
Methods included from Inspect
Constructor Details
permalink #initialize(machine, strict = true) ⇒ BuilderDsl
Returns a new instance of BuilderDsl.
24 25 26 27 28 29 |
# File 'lib/stupidedi/parser/builder_dsl.rb', line 24 def initialize(machine, strict = true) @machine = machine @strict = strict @reader = DslReader.new(Reader::Separators.empty, Reader::SegmentDict.empty) end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
permalink #method_missing(name, *args) (private)
[View source] [View on GitHub]
101 102 103 104 105 106 107 |
# File 'lib/stupidedi/parser/builder_dsl.rb', line 101 def method_missing(name, *args) if SEGMENT_ID =~ name.to_s segment!(name, Reader::Position.caller(2), *args) else super end end |
Instance Attribute Details
permalink #machine ⇒ StateMachine (readonly)
14 15 16 |
# File 'lib/stupidedi/parser/builder_dsl.rb', line 14 def machine @machine end |
permalink #reader ⇒ DslReader (readonly)
20 21 22 |
# File 'lib/stupidedi/parser/builder_dsl.rb', line 20 def reader @reader end |
permalink #strict=(value) ⇒ Boolean (writeonly)
17 18 19 |
# File 'lib/stupidedi/parser/builder_dsl.rb', line 17 def strict=(value) @strict = value end |
Class Method Details
permalink .build(config, strict = true) ⇒ BuilderDsl
260 261 262 |
# File 'lib/stupidedi/parser/builder_dsl.rb', line 260 def build(config, strict = true) new(StateMachine.build(config), strict) end |
Instance Method Details
permalink #respond_to_missing?(name, include_private = false) ⇒ Boolean
31 32 33 |
# File 'lib/stupidedi/parser/builder_dsl.rb', line 31 def respond_to_missing?(name, include_private = false) SEGMENT_ID =~ name.to_s || super end |
permalink #segment!(name, position, *elements) ⇒ BuilderDsl
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 |
# File 'lib/stupidedi/parser/builder_dsl.rb', line 40 def segment!(name, position, *elements) segment_tok = mksegment_tok(@reader.segment_dict, name, elements, position) machine, reader = @machine.insert(segment_tok, @strict, @reader) if @strict unless machine.deterministic? matches = machine.active.map do |m| segment_def = m.node.zipper.node.definition "#{segment_def.id} #{segment_def.name}" end.join(", ") raise Exceptions::ParseError, "non-deterministic machine state: #{matches}" end # Validate the new segment (recursively, including its children) machine.active.each{|m| critique(m.node.zipper) } # We want to detect when we've ended a syntax node (or more), like # starting a new interchange will end all previously "open" syntax # nodes. So we compare the state before adding `segment_tok` to the # corresponding state after we've added `segment_tok`. machine.prev.tap do |prev| prev.active.zip(machine.active) do |p, q| # If the new state `q` is a descendent of `p`, we know that `p` # and all of its ancestors are unterminated. However, if `q` is # not a descendent of `p`, but is a descendent of one of `p`s # descendents, then `p` and perhaps some of its ancestors were # terminated when the state transitioned to `q`. qancestors = Set.new # Operate on the syntax tree (instead of the state tree) q = q.node.zipper p = p.node.zipper while q.respond_to?(:parent) qancestors << q.parent q = q.parent end while p.respond_to?(:parent) break if qancestors.include?(p) # Now that we're sure that this syntax node (loop, table, etc) # is done being constructed, we can perform more validations. critique(p) p = p.parent end end end end @machine = machine @reader = reader self end |
permalink #strict? ⇒ Boolean
35 36 37 |
# File 'lib/stupidedi/parser/builder_dsl.rb', line 35 def strict? @strict end |