Class: Ibex::Frontend::TokenAdapter::RuleState
- Inherits:
-
Object
- Object
- Ibex::Frontend::TokenAdapter::RuleState
- Defined in:
- lib/ibex/frontend/token_adapter/rule_state.rb,
sig/ibex/frontend/token_adapter/rule_state.rbs
Overview
Classifies context-dependent tokens in the grammar rule section.
Constant Summary collapse
- SCALAR_TYPES =
{ literal: :LITERAL, integer: :INTEGER, action: :ACTION, user_code: :USER_CODE }.freeze
Instance Attribute Summary collapse
- #section ⇒ parser_section readonly
- #state ⇒ Symbol readonly
Instance Method Summary collapse
- #adjacent?(left, right) ⇒ Boolean
- #classify(token, remaining, last_external:, previous_external:) ⇒ external_token
- #classify_identifier(token, remaining, last_external, previous_external) ⇒ external_token
- #classify_inline ⇒ external_token
- #classify_punctuation(token) ⇒ external_token
- #classify_rhs_identifier(token, remaining) ⇒ external_token
- #expectation(token) ⇒ String?
- #finish_rules ⇒ external_token
- #group_opening ⇒ Token?
-
#initialize ⇒ RuleState
constructor
A new instance of RuleState.
- #named_reference_name?(last_external, previous_external) ⇒ Boolean
- #open_delimiter_kind ⇒ delimiter_kind?
- #parameter_definition_tail?(tail) ⇒ Boolean
- #parameterized_call?(token, following) ⇒ Boolean
- #parameterized_rule_boundary?(token, remaining) ⇒ Boolean
- #reset_rule_boundary ⇒ void
- #rule_boundary?(token, following) ⇒ Boolean
- #rule_lhs(token) ⇒ external_token
- #rules_lhs_expectation(token) ⇒ String
- #separated_list_call?(token, following) ⇒ Boolean
- #separated_terminal(token) ⇒ external_token
- #start_rule(token) ⇒ external_token
- #string_value(token) ⇒ String
Constructor Details
#initialize ⇒ RuleState
Returns a new instance of RuleState.
21 22 23 24 25 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 21 def initialize @state = :rules_lhs @section = :rules @delimiters = DelimiterTracker.new end |
Instance Attribute Details
#section ⇒ parser_section (readonly)
12 13 14 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 12 def section @section end |
#state ⇒ Symbol (readonly)
13 14 15 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 13 def state @state end |
Instance Method Details
#adjacent?(left, right) ⇒ Boolean
181 182 183 184 185 186 187 188 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 181 def adjacent?(left, right) left_span = left.span right_span = right.span return left_span.end_byte == right_span.start_byte if left_span && right_span left.location.line == right.location.line && left.location.column + string_value(left).length == right.location.column end |
#classify(token, remaining, last_external:, previous_external:) ⇒ external_token
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 29 def classify(token, remaining, last_external:, previous_external:) external = if token.type == :identifier classify_identifier(token, remaining, last_external, previous_external) elsif token.type == :node @node_annotation = true :NODE elsif token.type == :inline classify_inline elsif token.type == :empty :EMPTY elsif SCALAR_TYPES.key?(token.type) SCALAR_TYPES.fetch(token.type) else classify_punctuation(token) end @delimiters.observe(token, external, last_external) @node_annotation = false if token.type == :")" && @node_annotation external end |
#classify_identifier(token, remaining, last_external, previous_external) ⇒ external_token
80 81 82 83 84 85 86 87 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 80 def classify_identifier(token, remaining, last_external, previous_external) return :IDENTIFIER if @node_annotation return rule_lhs(token) if @state == :rules_lhs return :IDENTIFIER unless @state == :rule_rhs return :IDENTIFIER if named_reference_name?(last_external, previous_external) classify_rhs_identifier(token, remaining) end |
#classify_inline ⇒ external_token
73 74 75 76 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 73 def classify_inline reset_rule_boundary if @state == :rule_rhs && @delimiters.empty? :INLINE end |
#classify_punctuation(token) ⇒ external_token
191 192 193 194 195 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 191 def classify_punctuation(token) @state = :rule_rhs if @state == :rule_colon && token.type == :":" reset_rule_boundary if @state == :rule_rhs && token.type == :";" && @delimiters.empty? string_value(token) end |
#classify_rhs_identifier(token, remaining) ⇒ external_token
90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 90 def classify_rhs_identifier(token, remaining) value = string_value(token) return :IDENTIFIER if value == "end" && @delimiters.open_kind return finish_rules if value == "end" following = remaining.first return :IDENTIFIER unless following return start_rule(token) if rule_boundary?(token, following) || parameterized_rule_boundary?(token, remaining) return separated_terminal(token) if separated_list_call?(token, following) return :PARAMETERIZED_REFERENCE if parameterized_call?(token, following) :IDENTIFIER end |
#expectation(token) ⇒ String?
60 61 62 63 64 65 66 67 68 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 60 def expectation(token) if @state == :rules_lhs && @section == :rules rules_lhs_expectation(token) elsif @state == :rule_colon ":" elsif @state == :rule_rhs && %w[) ,].include?(token&.value) "a grammar symbol" end end |
#finish_rules ⇒ external_token
160 161 162 163 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 160 def finish_rules @section = :user_code :END end |
#group_opening ⇒ Token?
50 51 52 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 50 def group_opening @delimiters.group_opening end |
#named_reference_name?(last_external, previous_external) ⇒ Boolean
119 120 121 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 119 def named_reference_name?(last_external, previous_external) last_external == ":" && %i[IDENTIFIER LITERAL].include?(previous_external) end |
#open_delimiter_kind ⇒ delimiter_kind?
55 56 57 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 55 def open_delimiter_kind @delimiters.open_kind end |
#parameter_definition_tail?(tail) ⇒ Boolean
142 143 144 145 146 147 148 149 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 142 def parameter_definition_tail?(tail) closing = tail.index { |entry| entry.type == :")" } return false unless closing && tail[closing + 1]&.type == :":" formals = tail.take(closing) !formals.empty? && formals.length.odd? && formals.each_with_index.all? { |entry, index| entry.type == (index.even? ? :identifier : :",") } end |
#parameterized_call?(token, following) ⇒ Boolean
176 177 178 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 176 def parameterized_call?(token, following) following.type == :"(" && adjacent?(token, following) end |
#parameterized_rule_boundary?(token, remaining) ⇒ Boolean
132 133 134 135 136 137 138 139 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 132 def parameterized_rule_boundary?(token, remaining) lhs_column = @lhs_column opening = remaining.first return false unless lhs_column && @delimiters.empty? && token.location.column <= lhs_column return false unless opening&.type == :"(" && adjacent?(token, opening) parameter_definition_tail?(remaining.drop(1)) end |
#reset_rule_boundary ⇒ void
This method returns an undefined value.
198 199 200 201 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 198 def reset_rule_boundary @lhs_column = nil @state = :rules_lhs end |
#rule_boundary?(token, following) ⇒ Boolean
124 125 126 127 128 129 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 124 def rule_boundary?(token, following) lhs_column = @lhs_column return false unless lhs_column @delimiters.empty? && following.type == :":" && token.location.column <= lhs_column end |
#rule_lhs(token) ⇒ external_token
106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 106 def rule_lhs(token) if string_value(token) == "end" @section = :user_code return :END end @rule_seen = true @lhs_column = token.location.column @state = :rule_colon :LHS end |
#rules_lhs_expectation(token) ⇒ String
204 205 206 207 208 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 204 def rules_lhs_expectation(token) return "identifier" unless token&.type == :eof @rule_seen ? "end" : "at least one rule" end |
#separated_list_call?(token, following) ⇒ Boolean
166 167 168 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 166 def separated_list_call?(token, following) %w[separated_list separated_nonempty_list].include?(string_value(token)) && following.type == :"(" end |
#separated_terminal(token) ⇒ external_token
171 172 173 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 171 def separated_terminal(token) string_value(token) == "separated_list" ? :SEPARATED_LIST : :SEPARATED_NONEMPTY_LIST end |
#start_rule(token) ⇒ external_token
152 153 154 155 156 157 |
# File 'lib/ibex/frontend/token_adapter/rule_state.rb', line 152 def start_rule(token) @rule_seen = true @lhs_column = token.location.column @state = :rule_colon :LHS end |