Module: Taipo::Parser
- Defined in:
- lib/taipo/parser.rb,
lib/taipo/parser/stack.rb,
lib/taipo/parser/validater.rb,
lib/taipo/parser/syntax_state.rb
Overview
A parser of Taipo type definitions
Defined Under Namespace
Modules: Validater Classes: Stack, SyntaxState
Class Method Summary collapse
-
.escape?(c, states) ⇒ Boolean, Hash<Symbol,Boolean>
private
Check whether the character should be skipped.
-
.parse(str) ⇒ Taipo:TypeElements
Return a Taipo::TypeElements object based on
str
. -
.parse_constraint(str) ⇒ String
private
Parse the constraint expressed as a string.
-
.process_collection(direction, stack, name:) ⇒ Taipo::Parser::Stack
private
Process a collection.
-
.process_component(stack, name:) ⇒ Taipo::Parser::Stack
private
Process a component.
-
.process_constraint(stack, raw:) ⇒ Taipo::Parser::Stack
private
Process a constraint.
-
.process_constraints(stack, chars:, index:) ⇒ Taipo::Parser::Stack, Integer
private
Process a series of constraints.
-
.process_end(stack, name:) ⇒ Taipo::Parser::Stack
private
Process the end of the type definition.
-
.process_name(stack, name:) ⇒ Taipo::Parser::Stack
private
Process the name of a TypeElement.
-
.process_subject(stack, name:, subject:) ⇒ Taipo::Parser::Stack
private
Process the subject of a series of constraints.
-
.process_sum(stack, name:) ⇒ Taipo::Parser::Stack
private
Process a sum of types.
Class Method Details
.escape?(c, states) ⇒ Boolean, Hash<Symbol,Boolean>
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Check whether the character should be skipped
This method determines whether a particular character c
should be skipped based on states
. It also updates states
.
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/taipo/parser.rb', line 88 def self.escape?(c, states) if states[:esc] states[:esc] = false return skip, states end skip = true case c when "'" states[:ss] = !states[:ss] unless states[:re] || states[:ds] when '"' states[:ds] = !states[:ds] unless states[:re] || states[:ss] when '/' states[:re] = !states[:re] unless states[:ss] || states[:ds] when '\\' states[:esc] = true else skip = false end return skip, states end |
.parse(str) ⇒ Taipo:TypeElements
Return a Taipo::TypeElements object based on str
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 70 71 72 73 |
# File 'lib/taipo/parser.rb', line 30 def self.parse(str) Taipo::Parser::Validater.validate str stack = Taipo::Parser::Stack.new i = 0 subject = :implied chars = str.chars content = '' while (i < chars.size) reset = true case chars[i] when ' ' i += 1 next when '|' stack = process_sum stack, name: content subject = :implied when '<' stack = process_collection :open, stack, name: content subject = :implied when '>' stack = process_collection :close, stack, name: content subject = :made when ',' stack = process_component stack, name: content subject = :implied when '(' stack = process_subject stack, name: content, subject: subject stack, i = process_constraints stack, chars: chars, index: i+1 else reset = false subject = :unmade end content = (reset) ? '' : content + chars[i] i += 1 end stack = process_end stack, name: content stack.result end |
.parse_constraint(str) ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
If the constraint is in the form of an instance method (eg. #foo) this method uses TypeElement::Constraint::METHOD as the name returned.
Parse the constraint expressed as a string
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/taipo/parser.rb', line 124 def self.parse_constraint(str) str.strip! in_name = nil name = '' content = '' str.each_char do |c| if c == '#' && in_name.nil? name = Taipo::TypeElement::Constraint::METHOD in_name = false elsif c == ':' && in_name.nil? name = 'val' content = content + c in_name = false elsif c == ':' && in_name name = content content = '' in_name = false else content = content + c in_name = true if in_name.nil? end end value = content.strip return name, value end |
.process_collection(direction, stack, name:) ⇒ Taipo::Parser::Stack
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Process a collection
This method either adds or updates a collection on stack
depending on direction
. If direction
is :open
, this adds a TypeElement to stack
representing the class of the collection. If direction
is :close
, this adds a TypeElement to stack
representing the class of the final component of the collection.
169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/taipo/parser.rb', line 169 def self.process_collection(direction, stack, name:) case direction when :open stack = process_name stack, name: name stack.add_children when :close stack = process_name stack, name: name unless name.empty? children = stack.remove_children stack.update_element :children=, children end end |
.process_component(stack, name:) ⇒ Taipo::Parser::Stack
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Process a component
This method adds a TypeElement to stack
representing a component of a collection.
194 195 196 197 |
# File 'lib/taipo/parser.rb', line 194 def self.process_component(stack, name:) stack = process_name stack, name: name stack.add_child end |
.process_constraint(stack, raw:) ⇒ Taipo::Parser::Stack
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Process a constraint
This method adds a TypeElement::Constraint to the last element in stack
.
211 212 213 214 |
# File 'lib/taipo/parser.rb', line 211 def self.process_constraint(stack, raw:) n, v = parse_constraint raw stack.add_constraint Taipo::TypeElement::Constraint.new(name: n, value: v) end |
.process_constraints(stack, chars:, index:) ⇒ Taipo::Parser::Stack, Integer
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Process a series of constraints
This method adds a TypeElement::Constraints to the last element in stack
. Because it parses chars
, it also returns an updated index
.
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/taipo/parser.rb', line 230 def self.process_constraints(stack, chars:, index:) stack.add_constraints inside = { ss: false, ds: false, re: false, esc: false } content = '' while (index < chars.size) skip, inside = escape?(chars[index], inside) if skip content = content + chars[index] index += 1 next end case chars[index] when ')' stack = process_constraint stack, raw: content break when ',' stack = process_constraint stack, raw: content content = '' else content = content + chars[index] end index += 1 end constraints = stack.remove_constraints stack.update_element :constraints=, constraints return stack, index end |
.process_end(stack, name:) ⇒ Taipo::Parser::Stack
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Process the end of the type definition
The design of parse means that at the end of the loop, an element may remain to be added. This method add any remaining element to stack
.
278 279 280 281 282 |
# File 'lib/taipo/parser.rb', line 278 def self.process_end(stack, name:) return stack if name.empty? process_name stack, name: name end |
.process_name(stack, name:) ⇒ Taipo::Parser::Stack
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Taipo allows certain bare constraints to be written in type definitions. If name
is a bare constraint (either an instance method or a symbol), this method adds a TypeElement representing the Object class with the relevant constraint.
Process the name of a TypeElement
This method adds a TypeElement to stack
with the name name
.
301 302 303 304 305 306 307 308 309 310 |
# File 'lib/taipo/parser.rb', line 301 def self.process_name(stack, name:) if name. chars = "(#{name})".chars stack = process_subject stack, name: '', subject: :implied stack, i = process_constraints stack, chars: chars, index: 1 stack else stack.add_element name: name end end |
.process_subject(stack, name:, subject:) ⇒ Taipo::Parser::Stack
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Process the subject of a series of constraints
Taipo allows for a type definition to specify a series of constraints that constrain the particular type (the subject). This method adds a TypeElement to stack
depending on the value of subject
.
327 328 329 330 331 332 333 334 335 336 |
# File 'lib/taipo/parser.rb', line 327 def self.process_subject(stack, name:, subject:) case subject when :made stack when :unmade process_name stack, name: name when :implied process_name stack, name: 'Object' end end |
.process_sum(stack, name:) ⇒ Taipo::Parser::Stack
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Process a sum of types
This method adds a TypeElement to stack
representing the former of the types in the sum.
351 352 353 354 355 |
# File 'lib/taipo/parser.rb', line 351 def self.process_sum(stack, name:) return stack if name.empty? process_name stack, name: name end |