Class: Ibex::IR::Validator::LexerDocument
- Defined in:
- lib/ibex/ir/validator/lexer.rb,
sig/ibex/ir/validator/lexer.rbs
Overview
Structural validation for the independently versioned Lexer IR.
Constant Summary collapse
- ROOT_REQUIRED =
%w[ ibex_ir schema_version initial_state states rules warnings source_provenance ].freeze
- RULE_REQUIRED =
%w[ id state kind token pattern pattern_kind options action loc ].freeze
Constants inherited from Base
Instance Method Summary collapse
-
#initialize(data, path: "$") ⇒ LexerDocument
constructor
A new instance of LexerDocument.
- #validate ⇒ self
- #validate_pattern(rule, path, options) ⇒ void
- #validate_rules ⇒ void
- #validate_source_provenance ⇒ void
- #validate_states ⇒ void
- #validate_warnings ⇒ void
Methods inherited from Base
#array, #boolean, #child_path, #enum, #field, #integer, #invalid, #literal, #location, #metadata, #nonempty_string, #nonnegative_integer, #nullable_string, #object, #positive_integer, #record, #string
Constructor Details
#initialize(data, path: "$") ⇒ LexerDocument
Returns a new instance of LexerDocument.
16 17 18 19 20 |
# File 'lib/ibex/ir/validator/lexer.rb', line 16 def initialize(data, path: "$") super() @data = data @path = path end |
Instance Method Details
#validate ⇒ self
23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/ibex/ir/validator/lexer.rb', line 23 def validate record(@data, @path, ROOT_REQUIRED) literal(@data["ibex_ir"], "#{@path}.ibex_ir", "lexer") literal(@data["schema_version"], "#{@path}.schema_version", LEXER_SCHEMA_VERSION) literal(@data["initial_state"], "#{@path}.initial_state", "INITIAL") validate_states validate_rules validate_warnings validate_source_provenance self end |
#validate_pattern(rule, path, options) ⇒ void
This method returns an undefined value.
74 75 76 77 78 79 80 81 82 83 |
# File 'lib/ibex/ir/validator/lexer.rb', line 74 def validate_pattern(rule, path, ) flags = 0 flags |= Regexp::IGNORECASE if .include?("i") flags |= Regexp::MULTILINE if .include?("m") flags |= Regexp::EXTENDED if .include?("x") regexp = Regexp.new("\\A(?:#{rule.fetch('pattern')})", flags) invalid("#{path}.pattern", "must not match an empty string") if regexp.match?("") rescue RegexpError => e invalid("#{path}.pattern", "is not a valid regular expression: #{e.}") end |
#validate_rules ⇒ void
This method returns an undefined value.
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 |
# File 'lib/ibex/ir/validator/lexer.rb', line 51 def validate_rules # rubocop:disable Metrics/AbcSize array(@data["rules"], "#{@path}.rules").each_with_index do |value, index| path = "#{@path}.rules[#{index}]" rule = record(value, path, RULE_REQUIRED) literal(rule["id"], "#{path}.id", index) state = nonempty_string(rule["state"], "#{path}.state") invalid("#{path}.state", "references missing state #{state.inspect}") unless @states[state] kind = enum(rule["kind"], "#{path}.kind", %w[token skip on]) nullable_string(rule["token"], "#{path}.token") invalid("#{path}.token", "is required for token rules") if kind == "token" && rule["token"].nil? invalid("#{path}.token", "must be null for #{kind} rules") if kind != "token" && rule["token"] nonempty_string(rule["pattern"], "#{path}.pattern") enum(rule["pattern_kind"], "#{path}.pattern_kind", %w[regexp literal]) = string(rule["options"], "#{path}.options") invalid("#{path}.options", "may contain only i, m, and x") unless .match?(/\A[imx]*\z/) validate_pattern(rule, path, ) nullable_string(rule["action"], "#{path}.action") invalid("#{path}.action", "is required for on rules") if kind == "on" && rule["action"].nil? location(rule["loc"], "#{path}.loc", nullable: false) end end |
#validate_source_provenance ⇒ void
This method returns an undefined value.
97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/ibex/ir/validator/lexer.rb', line 97 def validate_source_provenance value = @data["source_provenance"] return if value.nil? record(value, "#{@path}.source_provenance", %w[file root byte_span]) nullable_string(value["file"], "#{@path}.source_provenance.file") nullable_string(value["root"], "#{@path}.source_provenance.root") return if value["byte_span"].nil? span = record(value["byte_span"], "#{@path}.source_provenance.byte_span", %w[start end]) nonnegative_integer(span["start"], "#{@path}.source_provenance.byte_span.start") nonnegative_integer(span["end"], "#{@path}.source_provenance.byte_span.end") end |
#validate_states ⇒ void
This method returns an undefined value.
38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/ibex/ir/validator/lexer.rb', line 38 def validate_states seen = {} #: Hash[String, bool] values = array(@data["states"], "#{@path}.states") invalid("#{@path}.states", "must start with INITIAL") unless values.first == "INITIAL" values.each_with_index do |value, index| name = nonempty_string(value, "#{@path}.states[#{index}]") invalid("#{@path}.states[#{index}]", "duplicates state #{name.inspect}") if seen[name] seen[name] = true end @states = seen end |
#validate_warnings ⇒ void
This method returns an undefined value.
86 87 88 89 90 91 92 93 94 |
# File 'lib/ibex/ir/validator/lexer.rb', line 86 def validate_warnings array(@data["warnings"], "#{@path}.warnings").each_with_index do |value, index| path = "#{@path}.warnings[#{index}]" warning = record(value, path, %w[type rule loc]) literal(warning["type"], "#{path}.type", "redos") nonnegative_integer(warning["rule"], "#{path}.rule") location(warning["loc"], "#{path}.loc", nullable: false) end end |