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.
-
.parse_definition(str) ⇒ Object
private
Return a Taipo::TypeElements object based on
str
. -
.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
.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/taipo/parser.rb', line 50 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
This method acts as a wrapping method to parse_definition. It first checks if the type definition has already been parsed and is in Taipo’s cache.
29 30 31 32 33 34 35 |
# File 'lib/taipo/parser.rb', line 29 def self.parse(str) if hit = Taipo::Cache[str] hit else Taipo::Cache[str] = Taipo::Parser.parse_definition str end 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
86 87 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 86 def self.parse_constraint(str) str.strip! in_name = nil name = '' content = '' str.each_char do |c| if c == '#' && in_name.nil? name = '#' 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 |
.parse_definition(str) ⇒ Object
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.
Return a Taipo::TypeElements object based on str
122 123 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 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 |
# File 'lib/taipo/parser.rb', line 122 def self.parse_definition(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 |
.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.
185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/taipo/parser.rb', line 185 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.
210 211 212 213 |
# File 'lib/taipo/parser.rb', line 210 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
.
227 228 229 230 |
# File 'lib/taipo/parser.rb', line 227 def self.process_constraint(stack, raw:) n, v = parse_constraint raw stack.add_constraint 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
.
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 |
# File 'lib/taipo/parser.rb', line 246 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
.
294 295 296 297 298 |
# File 'lib/taipo/parser.rb', line 294 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
.
317 318 319 320 321 322 323 324 325 326 |
# File 'lib/taipo/parser.rb', line 317 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
.
343 344 345 346 347 348 349 350 351 352 |
# File 'lib/taipo/parser.rb', line 343 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.
367 368 369 370 371 |
# File 'lib/taipo/parser.rb', line 367 def self.process_sum(stack, name:) return stack if name.empty? process_name stack, name: name end |