@@ -62,6 +62,7 @@ class Lexer
6262 %categories
6363 %start
6464 ) . freeze #: Array[String]
65+ IDENTIFIER_PATTERN = /[a-zA-Z_.][-a-zA-Z0-9_.]*/ . freeze #: Regexp
6566
6667 # @rbs (GrammarFile grammar_file) -> void
6768 def initialize ( grammar_file )
@@ -135,10 +136,10 @@ def lex_token
135136 return [ :STRING , Lrama ::Lexer ::Token ::Str . new ( s_value : %Q(#{ @scanner . matched } ) , location : location ) ]
136137 when @scanner . scan ( /\d +/ )
137138 return [ :INTEGER , Lrama ::Lexer ::Token ::Int . new ( s_value : Integer ( @scanner . matched ) , location : location ) ]
138- when @scanner . scan ( /([a-zA-Z_.][-a-zA-Z0-9_.]*)/ )
139+ when @scanner . scan ( IDENTIFIER_PATTERN )
139140 token = Lrama ::Lexer ::Token ::Ident . new ( s_value : @scanner . matched , location : location )
140141 type =
141- if @scanner . check ( / \s *( \[ \s *[a-zA-Z_.][-a-zA-Z0-9_.]* \s * \] )? \s *:/ )
142+ if identifier_colon?
142143 :IDENT_COLON
143144 else
144145 :IDENTIFIER
@@ -196,6 +197,36 @@ def lex_c_code
196197
197198 private
198199
200+ # @rbs () -> bool
201+ def identifier_colon?
202+ scanner = StringScanner . new ( @scanner . rest )
203+ skip_trivia ( scanner )
204+
205+ if scanner . scan ( /\[ / )
206+ skip_trivia ( scanner )
207+ return false unless scanner . scan ( IDENTIFIER_PATTERN )
208+
209+ skip_trivia ( scanner )
210+ return false unless scanner . scan ( /\] / )
211+ end
212+
213+ skip_trivia ( scanner )
214+ !scanner . scan ( /:/ ) . nil?
215+ end
216+
217+ # @rbs (StringScanner scanner) -> void
218+ def skip_trivia ( scanner )
219+ loop do
220+ case
221+ when scanner . scan ( /\s +/ )
222+ when scanner . scan ( /\/ \* [\s \S ]*?\* \/ / )
223+ when scanner . scan ( %r{//.*(?:\n |$)} )
224+ else
225+ return
226+ end
227+ end
228+ end
229+
199230 # @rbs () -> void
200231 def lex_comment
201232 until @scanner . eos? do
0 commit comments