Class: SoberSwag::Parser
- Inherits:
-
Object
- Object
- SoberSwag::Parser
- Defined in:
- lib/sober_swag/parser.rb
Overview
Parses a Dry-Types Schema into a set of nodes we can use to compile. This is mostly because the visitor pattern sucks and catamorphisms are nice.
Do not use this class directly, as it is not part of the public api. Instead, use classes from the Compiler namespace.
Instance Attribute Summary collapse
-
#found ⇒ Object
readonly
What other types did we find while parsing this type?.
Instance Method Summary collapse
-
#bind(other) ⇒ Object
Call
.to_syntax
on another node, putting any new classes it finds in the list of classes we found in the process. -
#initialize(node) ⇒ Parser
constructor
A new instance of Parser.
- #run_parser ⇒ Object
-
#to_syntax ⇒ SoberSwag::Nodes::Base
Compile to one of our internal nodes.
Constructor Details
#initialize(node) ⇒ Parser
Returns a new instance of Parser.
9 10 11 12 |
# File 'lib/sober_swag/parser.rb', line 9 def initialize(node) @node = node @found = Set.new end |
Instance Attribute Details
#found ⇒ Object (readonly)
What other types did we find while parsing this type?
77 78 79 |
# File 'lib/sober_swag/parser.rb', line 77 def found @found end |
Instance Method Details
#bind(other) ⇒ Object
Call .to_syntax
on another node, putting any new classes it finds
in the list of classes we found in the process.
If you're a big Haskell nerd, then this is >>=.
84 85 86 87 88 |
# File 'lib/sober_swag/parser.rb', line 84 def bind(other) result = other.to_syntax @found += other.found result end |
#run_parser ⇒ Object
71 72 73 |
# File 'lib/sober_swag/parser.rb', line 71 def run_parser [to_syntax, found] end |
#to_syntax ⇒ SoberSwag::Nodes::Base
Compile to one of our internal nodes.
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 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 |
# File 'lib/sober_swag/parser.rb', line 17 def to_syntax # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity case @node when Dry::Types::Default # we handle this elsewhere, so bind(Parser.new(@node.type)) when Dry::Types::Array::Member Nodes::List.new(bind(Parser.new(@node.member))) when Dry::Types::Enum Nodes::Enum.new(@node.values) when Dry::Types::Schema Nodes::Object.new( @node.map { |attr| bind(Parser.new(attr)) } ) when Dry::Types::Schema::Key Nodes::Attribute.new( @node.name, @node.required? && !@node.type.default?, bind(Parser.new(@node.type)), @node. ) when Dry::Types::Sum left = bind(Parser.new(@node.left)) right = bind(Parser.new(@node.right)) # special case booleans to just return the left value # this is because modeling a boolean as a sum type of # TrueClass and FalseClass is kinda weird, because they're # considered different types instead of different constructors, # which we don't want to do is_bool = [left, right].all? do |e| e.respond_to?(:value) && [TrueClass, FalseClass].include?(e.value) end if is_bool left else Nodes::Sum.new(left, right) end when Dry::Types::Constrained bind(Parser.new(@node.type)) when Dry::Types::Nominal if @node.respond_to?(:type) && @node.type.is_a?(Dry::Types::Constrained) bind(Parser.new(@node.type)) else = @node.primitive.respond_to?(:meta) ? @node.primitive. : {} # start off with the moral equivalent of NodeTree[String] Nodes::Primitive.new(@node.primitive, .merge(@node.)) end else # Inside of this case we have a class that is some user-defined type # We put it in our array of found types, and consider it a primitive @found.add(@node) Nodes::Primitive.new(@node, @node.respond_to?(:meta) ? @node. : {}) end end |