|
20 | 20 | require_relative "grammar/symbols" |
21 | 21 | require_relative "grammar/type" |
22 | 22 | require_relative "grammar/union" |
| 23 | +require_relative "grammar/token_pattern" |
| 24 | +require_relative "grammar/lex_prec" |
23 | 25 | require_relative "lexer" |
24 | 26 |
|
25 | 27 | module Lrama |
@@ -68,6 +70,8 @@ class Grammar |
68 | 70 | # @union: Union |
69 | 71 | # @precedences: Array[Precedence] |
70 | 72 | # @start_nterm: Lrama::Lexer::Token::Base? |
| 73 | + # @token_patterns: Array[Grammar::TokenPattern] |
| 74 | + # @lex_prec: Grammar::LexPrec |
71 | 75 |
|
72 | 76 | extend Forwardable |
73 | 77 |
|
@@ -100,6 +104,8 @@ class Grammar |
100 | 104 | attr_accessor :locations #: bool |
101 | 105 | attr_accessor :define #: Hash[String, String] |
102 | 106 | attr_accessor :required #: bool |
| 107 | + attr_reader :token_patterns #: Array[Grammar::TokenPattern] |
| 108 | + attr_reader :lex_prec #: Grammar::LexPrec |
103 | 109 |
|
104 | 110 | def_delegators "@symbols_resolver", :symbols, :nterms, :terms, :add_nterm, :add_term, :find_term_by_s_value, |
105 | 111 | :find_symbol_by_number!, :find_symbol_by_id!, :token_to_symbol, |
@@ -133,6 +139,9 @@ def initialize(rule_counter, locations, define = {}) |
133 | 139 | @required = false |
134 | 140 | @precedences = [] |
135 | 141 | @start_nterm = nil |
| 142 | + @token_patterns = [] |
| 143 | + @lex_prec = Grammar::LexPrec.new |
| 144 | + @token_pattern_counter = 0 |
136 | 145 |
|
137 | 146 | append_special_symbols |
138 | 147 | end |
@@ -304,6 +313,48 @@ def ielr_defined? |
304 | 313 | @define.key?('lr.type') && @define['lr.type'] == 'ielr' |
305 | 314 | end |
306 | 315 |
|
| 316 | + # @rbs () -> bool |
| 317 | + def pslr_defined? |
| 318 | + @define.key?('lr.type') && @define['lr.type'] == 'pslr' |
| 319 | + end |
| 320 | + |
| 321 | + # Add a token pattern from %token-pattern directive |
| 322 | + # @rbs (id: Lexer::Token::Ident, pattern: Lexer::Token::Regex, ?alias_name: String?, ?tag: Lexer::Token::Tag?, lineno: Integer) -> Grammar::TokenPattern |
| 323 | + def add_token_pattern(id:, pattern:, alias_name: nil, tag: nil, lineno:) |
| 324 | + token_pattern = Grammar::TokenPattern.new( |
| 325 | + id: id, |
| 326 | + pattern: pattern, |
| 327 | + alias_name: alias_name, |
| 328 | + tag: tag, |
| 329 | + lineno: lineno, |
| 330 | + definition_order: @token_pattern_counter |
| 331 | + ) |
| 332 | + @token_pattern_counter += 1 |
| 333 | + @token_patterns << token_pattern |
| 334 | + |
| 335 | + # Also register as a terminal symbol |
| 336 | + add_term(id: id, alias_name: alias_name, tag: tag) |
| 337 | + |
| 338 | + token_pattern |
| 339 | + end |
| 340 | + |
| 341 | + # Add a lex-prec rule from %lex-prec directive |
| 342 | + # @rbs (left_token: Lexer::Token::Ident, operator: Symbol, right_token: Lexer::Token::Ident, lineno: Integer) -> Grammar::LexPrec::Rule |
| 343 | + def add_lex_prec_rule(left_token:, operator:, right_token:, lineno:) |
| 344 | + @lex_prec.add_rule( |
| 345 | + left_token: left_token, |
| 346 | + operator: operator, |
| 347 | + right_token: right_token, |
| 348 | + lineno: lineno |
| 349 | + ) |
| 350 | + end |
| 351 | + |
| 352 | + # Find a token pattern by its name |
| 353 | + # @rbs (String name) -> Grammar::TokenPattern? |
| 354 | + def find_token_pattern(name) |
| 355 | + @token_patterns.find { |tp| tp.name == name } |
| 356 | + end |
| 357 | + |
307 | 358 | private |
308 | 359 |
|
309 | 360 | # @rbs () -> void |
|
0 commit comments