class Parser::Lexer
line 3 “lib/parser/lexer.rl”
BEFORE YOU START ===¶ ↑
Read the Ruby Hacking Guide chapter 11, available in English at whitequark.org/blog/2013/04/01/ruby-hacking-guide-ch-11-finite-state-lexer/
Remember two things about Ragel scanners:
1) Longest match wins. 2) If two matches have the same length, the first in source code wins.
General rules of making Ragel and Bison happy:
* `p` (position) and `@te` contain the index of the character they're pointing to ("current"), plus one. `@ts` contains the index of the corresponding character. The code for extracting matched token is: @source_buffer.slice(@ts...@te) * If your input is `foooooooobar` and the rule is: 'f' 'o'+ the result will be: foooooooobar ^ ts=0 ^ p=te=9 * A Ragel lexer action should not emit more than one token, unless you know what you are doing. * All Ragel commands (fnext, fgoto, ...) end with a semicolon. * If an action emits the token and transitions to another state, use these Ragel commands: emit($whatever) fnext $next_state; fbreak; If you perform `fgoto` in an action which does not emit a token nor rewinds the stream pointer, the parser's side-effectful, context-sensitive lookahead actions will break in a hard to detect and debug way. * If an action does not emit a token: fgoto $next_state; * If an action features lookbehind, i.e. matches characters with the intent of passing them to another action: p = @ts - 1 fgoto $next_state; or, if the lookbehind consists of a single character: fhold; fgoto $next_state; * Ragel merges actions. So, if you have `e_lparen = '(' %act` and `c_lparen = '('` and a lexer action `e_lparen | c_lparen`, the result _will_ invoke the action `act`. e_something stands for "something with **e**mbedded action". * EOF is explicit and is matched by `c_eof`. If you want to introspect the state of the lexer, add this rule to the state: c_eof => do_eof; * If you proceed past EOF, the lexer will complain: NoMethodError: undefined method `ord' for nil:NilClass
Constants
- ESCAPES
line 82 “lib/parser/lexer.rl” %
- KEYWORDS
- KEYWORDS_BEGIN
- LEX_STATES
- PUNCTUATION
Mapping of strings to parser tokens.
- PUNCTUATION_BEGIN
- REGEXP_META_CHARACTERS
Attributes
_lex_eof_trans[RW]
_lex_from_state_actions[RW]
_lex_index_offsets[RW]
_lex_indicies[RW]
_lex_key_spans[RW]
_lex_to_state_actions[RW]
_lex_trans_actions[RW]
_lex_trans_keys[RW]
_lex_trans_targs[RW]
lex_en_expr_arg[RW]
lex_en_expr_beg[RW]
lex_en_expr_cmdarg[RW]
lex_en_expr_dot[RW]
lex_en_expr_end[RW]
lex_en_expr_endarg[RW]
lex_en_expr_endfn[RW]
lex_en_expr_fname[RW]
lex_en_expr_labelarg[RW]
lex_en_expr_mid[RW]
lex_en_expr_value[RW]
lex_en_expr_variable[RW]
lex_en_interp_backslash_delimited[RW]
lex_en_interp_backslash_delimited_words[RW]
lex_en_interp_string[RW]
lex_en_interp_words[RW]
lex_en_leading_dot[RW]
lex_en_line_begin[RW]
lex_en_line_comment[RW]
lex_en_plain_backslash_delimited[RW]
lex_en_plain_backslash_delimited_words[RW]
lex_en_plain_string[RW]
lex_en_plain_words[RW]
lex_en_regexp_modifiers[RW]
lex_error[RW]
lex_start[RW]
cmdarg[RW]
cmdarg_stack[R]
command_start[RW]
comments[RW]
cond[RW]
cond_stack[R]
context[RW]
diagnostics[RW]
force_utf32[RW]
in_kwarg[RW]
lambda_stack[R]
paren_nest[R]
source_buffer[R]
static_env[RW]
tokens[RW]
Public Class Methods
new(version)
click to toggle source
# File lib/parser/lexer.rb, line 10808 def initialize(version) @version = version @static_env = nil @context = nil @tokens = nil @comments = nil reset end
Public Instance Methods
advance()
click to toggle source
Return next token: [type, value].
# File lib/parser/lexer.rb, line 10966 def advance if @token_queue.any? return @token_queue.shift end # Ugly, but dependent on Ragel output. Consider refactoring it somehow. klass = self.class _lex_trans_keys = klass.send :_lex_trans_keys _lex_key_spans = klass.send :_lex_key_spans _lex_index_offsets = klass.send :_lex_index_offsets _lex_indicies = klass.send :_lex_indicies _lex_trans_targs = klass.send :_lex_trans_targs _lex_trans_actions = klass.send :_lex_trans_actions _lex_to_state_actions = klass.send :_lex_to_state_actions _lex_from_state_actions = klass.send :_lex_from_state_actions _lex_eof_trans = klass.send :_lex_eof_trans pe = @source_pts.size + 2 p, eof = @p, pe cmd_state = @command_start @command_start = false # line 10991 "lib/parser/lexer.rb" begin testEof = false _slen, _trans, _keys, _inds, _acts, _nacts = nil _goto_level = 0 _resume = 10 _eof_trans = 15 _again = 20 _test_eof = 30 _out = 40 while true if _goto_level <= 0 if p == pe _goto_level = _test_eof next end if @cs == 0 _goto_level = _out next end end if _goto_level <= _resume case _lex_from_state_actions[ @cs] when 97 then # line 1 "NONE" begin @ts = p end # line 11019 "lib/parser/lexer.rb" end _keys = @cs << 1 _inds = _lex_index_offsets[ @cs] _slen = _lex_key_spans[ @cs] _wide = ( (@source_pts[p] || 0)) _trans = if ( _slen > 0 && _lex_trans_keys[_keys] <= _wide && _wide <= _lex_trans_keys[_keys + 1] ) then _lex_indicies[ _inds + _wide - _lex_trans_keys[_keys] ] else _lex_indicies[ _inds + _slen ] end end if _goto_level <= _eof_trans @cs = _lex_trans_targs[_trans] if _lex_trans_actions[_trans] != 0 case _lex_trans_actions[_trans] when 28 then # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end when 117 then # line 822 "lib/parser/lexer.rl" begin @escape_s = p @escape = nil end when 29 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end when 59 then # line 1222 "lib/parser/lexer.rl" begin @sharp_s = p - 1 end when 63 then # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end when 304 then # line 1266 "lib/parser/lexer.rl" begin tm = p end when 36 then # line 1547 "lib/parser/lexer.rl" begin tm = p end when 38 then # line 1567 "lib/parser/lexer.rl" begin tm = p end when 40 then # line 1595 "lib/parser/lexer.rl" begin tm = p end when 70 then # line 1787 "lib/parser/lexer.rl" begin heredoc_e = p end when 343 then # line 1879 "lib/parser/lexer.rl" begin tm = p - 1; diag_msg = :ivar_name end when 346 then # line 1880 "lib/parser/lexer.rl" begin tm = p - 2; diag_msg = :cvar_name end when 354 then # line 1900 "lib/parser/lexer.rl" begin @escape = nil end when 383 then # line 1989 "lib/parser/lexer.rl" begin tm = p end when 302 then # line 2077 "lib/parser/lexer.rl" begin ident_tok = tok; ident_ts = @ts; ident_te = @te; end when 470 then # line 2263 "lib/parser/lexer.rl" begin @num_base = 16; @num_digits_s = p end when 464 then # line 2264 "lib/parser/lexer.rl" begin @num_base = 10; @num_digits_s = p end when 467 then # line 2265 "lib/parser/lexer.rl" begin @num_base = 8; @num_digits_s = p end when 461 then # line 2266 "lib/parser/lexer.rl" begin @num_base = 2; @num_digits_s = p end when 476 then # line 2267 "lib/parser/lexer.rl" begin @num_base = 10; @num_digits_s = @ts end when 438 then # line 2268 "lib/parser/lexer.rl" begin @num_base = 8; @num_digits_s = @ts end when 453 then # line 2269 "lib/parser/lexer.rl" begin @num_suffix_s = p end when 446 then # line 2326 "lib/parser/lexer.rl" begin @num_suffix_s = p end when 443 then # line 2327 "lib/parser/lexer.rl" begin @num_suffix_s = p end when 88 then # line 2515 "lib/parser/lexer.rl" begin tm = p end when 7 then # line 1 "NONE" begin @te = p+1 end when 113 then # line 1099 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal current_literal.flush_string current_literal.extend_content emit(:tSTRING_DBEG, '#{'.freeze) if current_literal.heredoc? current_literal.saved_herebody_s = @herebody_s @herebody_s = nil end current_literal.start_interp_brace @command_start = true @cs = 773; begin p += 1 _goto_level = _out next end end end when 5 then # line 1025 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal current_literal.flush_string current_literal.extend_content emit(:tSTRING_DVAR, nil, @ts, @ts + 1) p = @ts begin @stack[ @top] = @cs @top+= 1 @cs = 328 _goto_level = _again next end end end when 109 then # line 950 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal if @te == pe diagnostic :fatal, :string_eof, nil, range(current_literal.str_s, current_literal.str_s + 1) end if current_literal.heredoc? line = tok(@herebody_s, @ts).gsub(/\r+$/, ''.freeze) if version?(18, 19, 20) # See ruby:c48b4209c line = line.gsub(/\r.*$/, ''.freeze) end # Try ending the heredoc with the complete most recently # scanned line. @herebody_s always refers to the start of such line. if current_literal.nest_and_try_closing(line, @herebody_s, @ts) # Adjust @herebody_s to point to the next line. @herebody_s = @te # Continue regular lexing after the heredoc reference (<<END). p = current_literal.heredoc_e - 1 @cs = (pop_literal); begin p += 1 _goto_level = _out next end else # Calculate indentation level for <<~HEREDOCs. current_literal.infer_indent_level(line) # Ditto. @herebody_s = @te end else # Try ending the literal with a newline. if current_literal.nest_and_try_closing(tok, @ts, @te) @cs = (pop_literal); begin p += 1 _goto_level = _out next end end if @herebody_s # This is a regular literal intertwined with a heredoc. Like: # # p <<-foo+"1 # bar # foo # 2" # # which, incidentally, evaluates to "bar\n1\n2". p = @herebody_s - 1 @herebody_s = nil end end if current_literal.words? && !eof_codepoint?(@source_pts[p]) current_literal.extend_space @ts, @te else # A literal newline is appended if the heredoc was _not_ closed # this time (see fbreak above). See also Literal#nest_and_try_closing # for rationale of calling #flush_string here. current_literal.extend_string tok, @ts, @te current_literal.flush_string end end end when 108 then # line 871 "lib/parser/lexer.rl" begin @te = p+1 begin string = tok # tLABEL_END is only possible in non-cond context on >= 2.2 if @version >= 22 && !@cond.active? lookahead = @source_buffer.slice(@te...@te+2) end current_literal = literal if !current_literal.heredoc? && (token = current_literal.nest_and_try_closing(string, @ts, @te, lookahead)) if token[0] == :tLABEL_END p += 1 pop_literal @cs = 766; else @cs = (pop_literal); end begin p += 1 _goto_level = _out next end else current_literal.extend_string(string, @ts, @te) end end end when 115 then # line 1041 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin if @version >= 27 literal.extend_string(tok, @ts, @te) else message = tok.start_with?('#@@') ? :cvar_name : :ivar_name diagnostic :error, message, { :name => tok(@ts + 1, @te) }, range(@ts + 1, @te) end end end when 114 then # line 1025 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal current_literal.flush_string current_literal.extend_content emit(:tSTRING_DVAR, nil, @ts, @ts + 1) p = @ts begin @stack[ @top] = @cs @top+= 1 @cs = 328 _goto_level = _again next end end end when 111 then # line 1012 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin literal.extend_space @ts, @te end end when 112 then # line 871 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin string = tok # tLABEL_END is only possible in non-cond context on >= 2.2 if @version >= 22 && !@cond.active? lookahead = @source_buffer.slice(@te...@te+2) end current_literal = literal if !current_literal.heredoc? && (token = current_literal.nest_and_try_closing(string, @ts, @te, lookahead)) if token[0] == :tLABEL_END p += 1 pop_literal @cs = 766; else @cs = (pop_literal); end begin p += 1 _goto_level = _out next end else current_literal.extend_string(string, @ts, @te) end end end when 6 then # line 895 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 4 then # line 871 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin string = tok # tLABEL_END is only possible in non-cond context on >= 2.2 if @version >= 22 && !@cond.active? lookahead = @source_buffer.slice(@te...@te+2) end current_literal = literal if !current_literal.heredoc? && (token = current_literal.nest_and_try_closing(string, @ts, @te, lookahead)) if token[0] == :tLABEL_END p += 1 pop_literal @cs = 766; else @cs = (pop_literal); end begin p += 1 _goto_level = _out next end else current_literal.extend_string(string, @ts, @te) end end end when 142 then # line 1099 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal current_literal.flush_string current_literal.extend_content emit(:tSTRING_DBEG, '#{'.freeze) if current_literal.heredoc? current_literal.saved_herebody_s = @herebody_s @herebody_s = nil end current_literal.start_interp_brace @command_start = true @cs = 773; begin p += 1 _goto_level = _out next end end end when 10 then # line 1025 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal current_literal.flush_string current_literal.extend_content emit(:tSTRING_DVAR, nil, @ts, @ts + 1) p = @ts begin @stack[ @top] = @cs @top+= 1 @cs = 328 _goto_level = _again next end end end when 139 then # line 950 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal if @te == pe diagnostic :fatal, :string_eof, nil, range(current_literal.str_s, current_literal.str_s + 1) end if current_literal.heredoc? line = tok(@herebody_s, @ts).gsub(/\r+$/, ''.freeze) if version?(18, 19, 20) # See ruby:c48b4209c line = line.gsub(/\r.*$/, ''.freeze) end # Try ending the heredoc with the complete most recently # scanned line. @herebody_s always refers to the start of such line. if current_literal.nest_and_try_closing(line, @herebody_s, @ts) # Adjust @herebody_s to point to the next line. @herebody_s = @te # Continue regular lexing after the heredoc reference (<<END). p = current_literal.heredoc_e - 1 @cs = (pop_literal); begin p += 1 _goto_level = _out next end else # Calculate indentation level for <<~HEREDOCs. current_literal.infer_indent_level(line) # Ditto. @herebody_s = @te end else # Try ending the literal with a newline. if current_literal.nest_and_try_closing(tok, @ts, @te) @cs = (pop_literal); begin p += 1 _goto_level = _out next end end if @herebody_s # This is a regular literal intertwined with a heredoc. Like: # # p <<-foo+"1 # bar # foo # 2" # # which, incidentally, evaluates to "bar\n1\n2". p = @herebody_s - 1 @herebody_s = nil end end if current_literal.words? && !eof_codepoint?(@source_pts[p]) current_literal.extend_space @ts, @te else # A literal newline is appended if the heredoc was _not_ closed # this time (see fbreak above). See also Literal#nest_and_try_closing # for rationale of calling #flush_string here. current_literal.extend_string tok, @ts, @te current_literal.flush_string end end end when 138 then # line 871 "lib/parser/lexer.rl" begin @te = p+1 begin string = tok # tLABEL_END is only possible in non-cond context on >= 2.2 if @version >= 22 && !@cond.active? lookahead = @source_buffer.slice(@te...@te+2) end current_literal = literal if !current_literal.heredoc? && (token = current_literal.nest_and_try_closing(string, @ts, @te, lookahead)) if token[0] == :tLABEL_END p += 1 pop_literal @cs = 766; else @cs = (pop_literal); end begin p += 1 _goto_level = _out next end else current_literal.extend_string(string, @ts, @te) end end end when 144 then # line 1041 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin if @version >= 27 literal.extend_string(tok, @ts, @te) else message = tok.start_with?('#@@') ? :cvar_name : :ivar_name diagnostic :error, message, { :name => tok(@ts + 1, @te) }, range(@ts + 1, @te) end end end when 143 then # line 1025 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal current_literal.flush_string current_literal.extend_content emit(:tSTRING_DVAR, nil, @ts, @ts + 1) p = @ts begin @stack[ @top] = @cs @top+= 1 @cs = 328 _goto_level = _again next end end end when 141 then # line 871 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin string = tok # tLABEL_END is only possible in non-cond context on >= 2.2 if @version >= 22 && !@cond.active? lookahead = @source_buffer.slice(@te...@te+2) end current_literal = literal if !current_literal.heredoc? && (token = current_literal.nest_and_try_closing(string, @ts, @te, lookahead)) if token[0] == :tLABEL_END p += 1 pop_literal @cs = 766; else @cs = (pop_literal); end begin p += 1 _goto_level = _out next end else current_literal.extend_string(string, @ts, @te) end end end when 11 then # line 895 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 9 then # line 871 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin string = tok # tLABEL_END is only possible in non-cond context on >= 2.2 if @version >= 22 && !@cond.active? lookahead = @source_buffer.slice(@te...@te+2) end current_literal = literal if !current_literal.heredoc? && (token = current_literal.nest_and_try_closing(string, @ts, @te, lookahead)) if token[0] == :tLABEL_END p += 1 pop_literal @cs = 766; else @cs = (pop_literal); end begin p += 1 _goto_level = _out next end else current_literal.extend_string(string, @ts, @te) end end end when 167 then # line 950 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal if @te == pe diagnostic :fatal, :string_eof, nil, range(current_literal.str_s, current_literal.str_s + 1) end if current_literal.heredoc? line = tok(@herebody_s, @ts).gsub(/\r+$/, ''.freeze) if version?(18, 19, 20) # See ruby:c48b4209c line = line.gsub(/\r.*$/, ''.freeze) end # Try ending the heredoc with the complete most recently # scanned line. @herebody_s always refers to the start of such line. if current_literal.nest_and_try_closing(line, @herebody_s, @ts) # Adjust @herebody_s to point to the next line. @herebody_s = @te # Continue regular lexing after the heredoc reference (<<END). p = current_literal.heredoc_e - 1 @cs = (pop_literal); begin p += 1 _goto_level = _out next end else # Calculate indentation level for <<~HEREDOCs. current_literal.infer_indent_level(line) # Ditto. @herebody_s = @te end else # Try ending the literal with a newline. if current_literal.nest_and_try_closing(tok, @ts, @te) @cs = (pop_literal); begin p += 1 _goto_level = _out next end end if @herebody_s # This is a regular literal intertwined with a heredoc. Like: # # p <<-foo+"1 # bar # foo # 2" # # which, incidentally, evaluates to "bar\n1\n2". p = @herebody_s - 1 @herebody_s = nil end end if current_literal.words? && !eof_codepoint?(@source_pts[p]) current_literal.extend_space @ts, @te else # A literal newline is appended if the heredoc was _not_ closed # this time (see fbreak above). See also Literal#nest_and_try_closing # for rationale of calling #flush_string here. current_literal.extend_string tok, @ts, @te current_literal.flush_string end end end when 166 then # line 871 "lib/parser/lexer.rl" begin @te = p+1 begin string = tok # tLABEL_END is only possible in non-cond context on >= 2.2 if @version >= 22 && !@cond.active? lookahead = @source_buffer.slice(@te...@te+2) end current_literal = literal if !current_literal.heredoc? && (token = current_literal.nest_and_try_closing(string, @ts, @te, lookahead)) if token[0] == :tLABEL_END p += 1 pop_literal @cs = 766; else @cs = (pop_literal); end begin p += 1 _goto_level = _out next end else current_literal.extend_string(string, @ts, @te) end end end when 169 then # line 1012 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin literal.extend_space @ts, @te end end when 170 then # line 871 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin string = tok # tLABEL_END is only possible in non-cond context on >= 2.2 if @version >= 22 && !@cond.active? lookahead = @source_buffer.slice(@te...@te+2) end current_literal = literal if !current_literal.heredoc? && (token = current_literal.nest_and_try_closing(string, @ts, @te, lookahead)) if token[0] == :tLABEL_END p += 1 pop_literal @cs = 766; else @cs = (pop_literal); end begin p += 1 _goto_level = _out next end else current_literal.extend_string(string, @ts, @te) end end end when 173 then # line 950 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal if @te == pe diagnostic :fatal, :string_eof, nil, range(current_literal.str_s, current_literal.str_s + 1) end if current_literal.heredoc? line = tok(@herebody_s, @ts).gsub(/\r+$/, ''.freeze) if version?(18, 19, 20) # See ruby:c48b4209c line = line.gsub(/\r.*$/, ''.freeze) end # Try ending the heredoc with the complete most recently # scanned line. @herebody_s always refers to the start of such line. if current_literal.nest_and_try_closing(line, @herebody_s, @ts) # Adjust @herebody_s to point to the next line. @herebody_s = @te # Continue regular lexing after the heredoc reference (<<END). p = current_literal.heredoc_e - 1 @cs = (pop_literal); begin p += 1 _goto_level = _out next end else # Calculate indentation level for <<~HEREDOCs. current_literal.infer_indent_level(line) # Ditto. @herebody_s = @te end else # Try ending the literal with a newline. if current_literal.nest_and_try_closing(tok, @ts, @te) @cs = (pop_literal); begin p += 1 _goto_level = _out next end end if @herebody_s # This is a regular literal intertwined with a heredoc. Like: # # p <<-foo+"1 # bar # foo # 2" # # which, incidentally, evaluates to "bar\n1\n2". p = @herebody_s - 1 @herebody_s = nil end end if current_literal.words? && !eof_codepoint?(@source_pts[p]) current_literal.extend_space @ts, @te else # A literal newline is appended if the heredoc was _not_ closed # this time (see fbreak above). See also Literal#nest_and_try_closing # for rationale of calling #flush_string here. current_literal.extend_string tok, @ts, @te current_literal.flush_string end end end when 172 then # line 871 "lib/parser/lexer.rl" begin @te = p+1 begin string = tok # tLABEL_END is only possible in non-cond context on >= 2.2 if @version >= 22 && !@cond.active? lookahead = @source_buffer.slice(@te...@te+2) end current_literal = literal if !current_literal.heredoc? && (token = current_literal.nest_and_try_closing(string, @ts, @te, lookahead)) if token[0] == :tLABEL_END p += 1 pop_literal @cs = 766; else @cs = (pop_literal); end begin p += 1 _goto_level = _out next end else current_literal.extend_string(string, @ts, @te) end end end when 175 then # line 871 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin string = tok # tLABEL_END is only possible in non-cond context on >= 2.2 if @version >= 22 && !@cond.active? lookahead = @source_buffer.slice(@te...@te+2) end current_literal = literal if !current_literal.heredoc? && (token = current_literal.nest_and_try_closing(string, @ts, @te, lookahead)) if token[0] == :tLABEL_END p += 1 pop_literal @cs = 766; else @cs = (pop_literal); end begin p += 1 _goto_level = _out next end else current_literal.extend_string(string, @ts, @te) end end end when 182 then # line 1099 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal current_literal.flush_string current_literal.extend_content emit(:tSTRING_DBEG, '#{'.freeze) if current_literal.heredoc? current_literal.saved_herebody_s = @herebody_s @herebody_s = nil end current_literal.start_interp_brace @command_start = true @cs = 773; begin p += 1 _goto_level = _out next end end end when 13 then # line 1025 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal current_literal.flush_string current_literal.extend_content emit(:tSTRING_DVAR, nil, @ts, @ts + 1) p = @ts begin @stack[ @top] = @cs @top+= 1 @cs = 328 _goto_level = _again next end end end when 179 then # line 950 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal if @te == pe diagnostic :fatal, :string_eof, nil, range(current_literal.str_s, current_literal.str_s + 1) end if current_literal.heredoc? line = tok(@herebody_s, @ts).gsub(/\r+$/, ''.freeze) if version?(18, 19, 20) # See ruby:c48b4209c line = line.gsub(/\r.*$/, ''.freeze) end # Try ending the heredoc with the complete most recently # scanned line. @herebody_s always refers to the start of such line. if current_literal.nest_and_try_closing(line, @herebody_s, @ts) # Adjust @herebody_s to point to the next line. @herebody_s = @te # Continue regular lexing after the heredoc reference (<<END). p = current_literal.heredoc_e - 1 @cs = (pop_literal); begin p += 1 _goto_level = _out next end else # Calculate indentation level for <<~HEREDOCs. current_literal.infer_indent_level(line) # Ditto. @herebody_s = @te end else # Try ending the literal with a newline. if current_literal.nest_and_try_closing(tok, @ts, @te) @cs = (pop_literal); begin p += 1 _goto_level = _out next end end if @herebody_s # This is a regular literal intertwined with a heredoc. Like: # # p <<-foo+"1 # bar # foo # 2" # # which, incidentally, evaluates to "bar\n1\n2". p = @herebody_s - 1 @herebody_s = nil end end if current_literal.words? && !eof_codepoint?(@source_pts[p]) current_literal.extend_space @ts, @te else # A literal newline is appended if the heredoc was _not_ closed # this time (see fbreak above). See also Literal#nest_and_try_closing # for rationale of calling #flush_string here. current_literal.extend_string tok, @ts, @te current_literal.flush_string end end end when 178 then # line 871 "lib/parser/lexer.rl" begin @te = p+1 begin string = tok # tLABEL_END is only possible in non-cond context on >= 2.2 if @version >= 22 && !@cond.active? lookahead = @source_buffer.slice(@te...@te+2) end current_literal = literal if !current_literal.heredoc? && (token = current_literal.nest_and_try_closing(string, @ts, @te, lookahead)) if token[0] == :tLABEL_END p += 1 pop_literal @cs = 766; else @cs = (pop_literal); end begin p += 1 _goto_level = _out next end else current_literal.extend_string(string, @ts, @te) end end end when 184 then # line 1041 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin if @version >= 27 literal.extend_string(tok, @ts, @te) else message = tok.start_with?('#@@') ? :cvar_name : :ivar_name diagnostic :error, message, { :name => tok(@ts + 1, @te) }, range(@ts + 1, @te) end end end when 183 then # line 1025 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal current_literal.flush_string current_literal.extend_content emit(:tSTRING_DVAR, nil, @ts, @ts + 1) p = @ts begin @stack[ @top] = @cs @top+= 1 @cs = 328 _goto_level = _again next end end end when 181 then # line 871 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin string = tok # tLABEL_END is only possible in non-cond context on >= 2.2 if @version >= 22 && !@cond.active? lookahead = @source_buffer.slice(@te...@te+2) end current_literal = literal if !current_literal.heredoc? && (token = current_literal.nest_and_try_closing(string, @ts, @te, lookahead)) if token[0] == :tLABEL_END p += 1 pop_literal @cs = 766; else @cs = (pop_literal); end begin p += 1 _goto_level = _out next end else current_literal.extend_string(string, @ts, @te) end end end when 12 then # line 871 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin string = tok # tLABEL_END is only possible in non-cond context on >= 2.2 if @version >= 22 && !@cond.active? lookahead = @source_buffer.slice(@te...@te+2) end current_literal = literal if !current_literal.heredoc? && (token = current_literal.nest_and_try_closing(string, @ts, @te, lookahead)) if token[0] == :tLABEL_END p += 1 pop_literal @cs = 766; else @cs = (pop_literal); end begin p += 1 _goto_level = _out next end else current_literal.extend_string(string, @ts, @te) end end end when 186 then # line 950 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal if @te == pe diagnostic :fatal, :string_eof, nil, range(current_literal.str_s, current_literal.str_s + 1) end if current_literal.heredoc? line = tok(@herebody_s, @ts).gsub(/\r+$/, ''.freeze) if version?(18, 19, 20) # See ruby:c48b4209c line = line.gsub(/\r.*$/, ''.freeze) end # Try ending the heredoc with the complete most recently # scanned line. @herebody_s always refers to the start of such line. if current_literal.nest_and_try_closing(line, @herebody_s, @ts) # Adjust @herebody_s to point to the next line. @herebody_s = @te # Continue regular lexing after the heredoc reference (<<END). p = current_literal.heredoc_e - 1 @cs = (pop_literal); begin p += 1 _goto_level = _out next end else # Calculate indentation level for <<~HEREDOCs. current_literal.infer_indent_level(line) # Ditto. @herebody_s = @te end else # Try ending the literal with a newline. if current_literal.nest_and_try_closing(tok, @ts, @te) @cs = (pop_literal); begin p += 1 _goto_level = _out next end end if @herebody_s # This is a regular literal intertwined with a heredoc. Like: # # p <<-foo+"1 # bar # foo # 2" # # which, incidentally, evaluates to "bar\n1\n2". p = @herebody_s - 1 @herebody_s = nil end end if current_literal.words? && !eof_codepoint?(@source_pts[p]) current_literal.extend_space @ts, @te else # A literal newline is appended if the heredoc was _not_ closed # this time (see fbreak above). See also Literal#nest_and_try_closing # for rationale of calling #flush_string here. current_literal.extend_string tok, @ts, @te current_literal.flush_string end end end when 185 then # line 871 "lib/parser/lexer.rl" begin @te = p+1 begin string = tok # tLABEL_END is only possible in non-cond context on >= 2.2 if @version >= 22 && !@cond.active? lookahead = @source_buffer.slice(@te...@te+2) end current_literal = literal if !current_literal.heredoc? && (token = current_literal.nest_and_try_closing(string, @ts, @te, lookahead)) if token[0] == :tLABEL_END p += 1 pop_literal @cs = 766; else @cs = (pop_literal); end begin p += 1 _goto_level = _out next end else current_literal.extend_string(string, @ts, @te) end end end when 193 then # line 1099 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal current_literal.flush_string current_literal.extend_content emit(:tSTRING_DBEG, '#{'.freeze) if current_literal.heredoc? current_literal.saved_herebody_s = @herebody_s @herebody_s = nil end current_literal.start_interp_brace @command_start = true @cs = 773; begin p += 1 _goto_level = _out next end end end when 15 then # line 1025 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal current_literal.flush_string current_literal.extend_content emit(:tSTRING_DVAR, nil, @ts, @ts + 1) p = @ts begin @stack[ @top] = @cs @top+= 1 @cs = 328 _goto_level = _again next end end end when 189 then # line 950 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal if @te == pe diagnostic :fatal, :string_eof, nil, range(current_literal.str_s, current_literal.str_s + 1) end if current_literal.heredoc? line = tok(@herebody_s, @ts).gsub(/\r+$/, ''.freeze) if version?(18, 19, 20) # See ruby:c48b4209c line = line.gsub(/\r.*$/, ''.freeze) end # Try ending the heredoc with the complete most recently # scanned line. @herebody_s always refers to the start of such line. if current_literal.nest_and_try_closing(line, @herebody_s, @ts) # Adjust @herebody_s to point to the next line. @herebody_s = @te # Continue regular lexing after the heredoc reference (<<END). p = current_literal.heredoc_e - 1 @cs = (pop_literal); begin p += 1 _goto_level = _out next end else # Calculate indentation level for <<~HEREDOCs. current_literal.infer_indent_level(line) # Ditto. @herebody_s = @te end else # Try ending the literal with a newline. if current_literal.nest_and_try_closing(tok, @ts, @te) @cs = (pop_literal); begin p += 1 _goto_level = _out next end end if @herebody_s # This is a regular literal intertwined with a heredoc. Like: # # p <<-foo+"1 # bar # foo # 2" # # which, incidentally, evaluates to "bar\n1\n2". p = @herebody_s - 1 @herebody_s = nil end end if current_literal.words? && !eof_codepoint?(@source_pts[p]) current_literal.extend_space @ts, @te else # A literal newline is appended if the heredoc was _not_ closed # this time (see fbreak above). See also Literal#nest_and_try_closing # for rationale of calling #flush_string here. current_literal.extend_string tok, @ts, @te current_literal.flush_string end end end when 188 then # line 871 "lib/parser/lexer.rl" begin @te = p+1 begin string = tok # tLABEL_END is only possible in non-cond context on >= 2.2 if @version >= 22 && !@cond.active? lookahead = @source_buffer.slice(@te...@te+2) end current_literal = literal if !current_literal.heredoc? && (token = current_literal.nest_and_try_closing(string, @ts, @te, lookahead)) if token[0] == :tLABEL_END p += 1 pop_literal @cs = 766; else @cs = (pop_literal); end begin p += 1 _goto_level = _out next end else current_literal.extend_string(string, @ts, @te) end end end when 195 then # line 1041 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin if @version >= 27 literal.extend_string(tok, @ts, @te) else message = tok.start_with?('#@@') ? :cvar_name : :ivar_name diagnostic :error, message, { :name => tok(@ts + 1, @te) }, range(@ts + 1, @te) end end end when 194 then # line 1025 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal current_literal.flush_string current_literal.extend_content emit(:tSTRING_DVAR, nil, @ts, @ts + 1) p = @ts begin @stack[ @top] = @cs @top+= 1 @cs = 328 _goto_level = _again next end end end when 191 then # line 1012 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin literal.extend_space @ts, @te end end when 192 then # line 871 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin string = tok # tLABEL_END is only possible in non-cond context on >= 2.2 if @version >= 22 && !@cond.active? lookahead = @source_buffer.slice(@te...@te+2) end current_literal = literal if !current_literal.heredoc? && (token = current_literal.nest_and_try_closing(string, @ts, @te, lookahead)) if token[0] == :tLABEL_END p += 1 pop_literal @cs = 766; else @cs = (pop_literal); end begin p += 1 _goto_level = _out next end else current_literal.extend_string(string, @ts, @te) end end end when 14 then # line 871 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin string = tok # tLABEL_END is only possible in non-cond context on >= 2.2 if @version >= 22 && !@cond.active? lookahead = @source_buffer.slice(@te...@te+2) end current_literal = literal if !current_literal.heredoc? && (token = current_literal.nest_and_try_closing(string, @ts, @te, lookahead)) if token[0] == :tLABEL_END p += 1 pop_literal @cs = 766; else @cs = (pop_literal); end begin p += 1 _goto_level = _out next end else current_literal.extend_string(string, @ts, @te) end end end when 197 then # line 950 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal if @te == pe diagnostic :fatal, :string_eof, nil, range(current_literal.str_s, current_literal.str_s + 1) end if current_literal.heredoc? line = tok(@herebody_s, @ts).gsub(/\r+$/, ''.freeze) if version?(18, 19, 20) # See ruby:c48b4209c line = line.gsub(/\r.*$/, ''.freeze) end # Try ending the heredoc with the complete most recently # scanned line. @herebody_s always refers to the start of such line. if current_literal.nest_and_try_closing(line, @herebody_s, @ts) # Adjust @herebody_s to point to the next line. @herebody_s = @te # Continue regular lexing after the heredoc reference (<<END). p = current_literal.heredoc_e - 1 @cs = (pop_literal); begin p += 1 _goto_level = _out next end else # Calculate indentation level for <<~HEREDOCs. current_literal.infer_indent_level(line) # Ditto. @herebody_s = @te end else # Try ending the literal with a newline. if current_literal.nest_and_try_closing(tok, @ts, @te) @cs = (pop_literal); begin p += 1 _goto_level = _out next end end if @herebody_s # This is a regular literal intertwined with a heredoc. Like: # # p <<-foo+"1 # bar # foo # 2" # # which, incidentally, evaluates to "bar\n1\n2". p = @herebody_s - 1 @herebody_s = nil end end if current_literal.words? && !eof_codepoint?(@source_pts[p]) current_literal.extend_space @ts, @te else # A literal newline is appended if the heredoc was _not_ closed # this time (see fbreak above). See also Literal#nest_and_try_closing # for rationale of calling #flush_string here. current_literal.extend_string tok, @ts, @te current_literal.flush_string end end end when 196 then # line 871 "lib/parser/lexer.rl" begin @te = p+1 begin string = tok # tLABEL_END is only possible in non-cond context on >= 2.2 if @version >= 22 && !@cond.active? lookahead = @source_buffer.slice(@te...@te+2) end current_literal = literal if !current_literal.heredoc? && (token = current_literal.nest_and_try_closing(string, @ts, @te, lookahead)) if token[0] == :tLABEL_END p += 1 pop_literal @cs = 766; else @cs = (pop_literal); end begin p += 1 _goto_level = _out next end else current_literal.extend_string(string, @ts, @te) end end end when 199 then # line 1012 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin literal.extend_space @ts, @te end end when 200 then # line 1196 "lib/parser/lexer.rl" begin @te = p+1 begin emit(:tREGEXP_OPT, tok(@ts, @te - 1), @ts, @te - 1) p = p - 1; begin @cs = 781 _goto_level = _again next end end end when 201 then # line 1183 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin unknown_options = tok.scan(/[^imxouesn]/) if unknown_options.any? diagnostic :error, :regexp_options, { :options => unknown_options.join } end emit(:tREGEXP_OPT) @cs = 781; begin p += 1 _goto_level = _out next end end end when 16 then # line 1335 "lib/parser/lexer.rl" begin @te = p+1 begin if tok =~ /^\$([1-9][0-9]*)$/ emit(:tNTH_REF, tok(@ts + 1).to_i) elsif tok =~ /^\$([&`'+])$/ emit(:tBACK_REF) else emit(:tGVAR) end @cs = (stack_pop); begin p += 1 _goto_level = _out next end end end when 202 then # line 1335 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin if tok =~ /^\$([1-9][0-9]*)$/ emit(:tNTH_REF, tok(@ts + 1).to_i) elsif tok =~ /^\$([&`'+])$/ emit(:tBACK_REF) else emit(:tGVAR) end @cs = (stack_pop); begin p += 1 _goto_level = _out next end end end when 204 then # line 1348 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin if tok =~ /^@@[0-9]/ diagnostic :error, :cvar_name, { :name => tok } end emit(:tCVAR) @cs = (stack_pop); begin p += 1 _goto_level = _out next end end end when 203 then # line 1358 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin if tok =~ /^@[0-9]/ diagnostic :error, :ivar_name, { :name => tok } end emit(:tIVAR) @cs = (stack_pop); begin p += 1 _goto_level = _out next end end end when 225 then # line 1379 "lib/parser/lexer.rl" begin @te = p+1 begin emit_table(KEYWORDS_BEGIN); @cs = 446; begin p += 1 _goto_level = _out next end end end when 211 then # line 1387 "lib/parser/lexer.rl" begin @te = p+1 begin emit(:tIDENTIFIER) @cs = 446; begin p += 1 _goto_level = _out next end end end when 18 then # line 1391 "lib/parser/lexer.rl" begin @te = p+1 begin p = @ts - 1 @cs = 781; begin @stack[ @top] = @cs @top+= 1 @cs = 328 _goto_level = _again next end end end when 208 then # line 1400 "lib/parser/lexer.rl" begin @te = p+1 begin emit_table(PUNCTUATION) @cs = 446; begin p += 1 _goto_level = _out next end end end when 220 then # line 1404 "lib/parser/lexer.rl" begin @te = p+1 begin p = p - 1; p = p - 1; begin @cs = 781 _goto_level = _again next end end end when 20 then # line 1410 "lib/parser/lexer.rl" begin @te = p+1 begin if version?(23) type, delimiter = tok[0..-2], tok[-1].chr begin @cs = (push_literal(type, delimiter, @ts)) _goto_level = _again next end else p = @ts - 1 begin @cs = 781 _goto_level = _again next end end end end when 207 then # line 1423 "lib/parser/lexer.rl" begin @te = p+1 begin p = p - 1; begin @cs = 781 _goto_level = _again next end end end when 206 then # line 527 "lib/parser/lexer.rl" begin @te = p+1 begin # Sit at EOF indefinitely. #advance would return $eof each time. # This allows to feed the lexer more data if needed; this is only used # in tests. # # Note that this action is not embedded into e_eof like e_heredoc_nl and e_bs # below. This is due to the fact that scanner state at EOF is observed # by tests, and encapsulating it in a rule would break the introspection. p = p - 1; begin p += 1 _goto_level = _out next end end end when 224 then # line 1379 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit_table(KEYWORDS_BEGIN); @cs = 446; begin p += 1 _goto_level = _out next end end end when 221 then # line 1383 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tCONSTANT) @cs = 446; begin p += 1 _goto_level = _out next end end end when 223 then # line 1387 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tIDENTIFIER) @cs = 446; begin p += 1 _goto_level = _out next end end end when 218 then # line 1391 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = @ts - 1 @cs = 781; begin @stack[ @top] = @cs @top+= 1 @cs = 328 _goto_level = _again next end end end when 214 then # line 1400 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit_table(PUNCTUATION) @cs = 446; begin p += 1 _goto_level = _out next end end end when 219 then # line 1407 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = p - 1; begin @cs = 543 _goto_level = _again next end end end when 212 then # line 1420 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 217 then # line 1423 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = p - 1; begin @cs = 781 _goto_level = _again next end end end when 19 then # line 1400 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin emit_table(PUNCTUATION) @cs = 446; begin p += 1 _goto_level = _out next end end end when 17 then # line 1423 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin p = p - 1; begin @cs = 781 _goto_level = _again next end end end when 210 then # line 1 "NONE" begin case @act when 43 then begin begin p = (( @te))-1; end emit_table(KEYWORDS_BEGIN); @cs = 446; begin p += 1 _goto_level = _out next end end when 44 then begin begin p = (( @te))-1; end emit(:tCONSTANT) @cs = 446; begin p += 1 _goto_level = _out next end end when 45 then begin begin p = (( @te))-1; end emit(:tIDENTIFIER) @cs = 446; begin p += 1 _goto_level = _out next end end end end when 22 then # line 1435 "lib/parser/lexer.rl" begin @te = p+1 begin emit(:tLABEL, tok(@ts, @te - 2), @ts, @te - 1) p = p - 1; @cs = 766; begin p += 1 _goto_level = _out next end end end when 227 then # line 1441 "lib/parser/lexer.rl" begin @te = p+1 begin p = p - 1; begin @cs = 781 _goto_level = _again next end end end when 226 then # line 527 "lib/parser/lexer.rl" begin @te = p+1 begin # Sit at EOF indefinitely. #advance would return $eof each time. # This allows to feed the lexer more data if needed; this is only used # in tests. # # Note that this action is not embedded into e_eof like e_heredoc_nl and e_bs # below. This is due to the fact that scanner state at EOF is observed # by tests, and encapsulating it in a rule would break the introspection. p = p - 1; begin p += 1 _goto_level = _out next end end end when 229 then # line 1438 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 228 then # line 1441 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = p - 1; begin @cs = 781 _goto_level = _again next end end end when 21 then # line 1441 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin p = p - 1; begin @cs = 781 _goto_level = _again next end end end when 235 then # line 1467 "lib/parser/lexer.rl" begin @te = p+1 begin emit_table(PUNCTUATION) @cs = 474; begin p += 1 _goto_level = _out next end end end when 234 then # line 1473 "lib/parser/lexer.rl" begin @te = p+1 begin p = p - 1; begin @cs = 781 _goto_level = _again next end end end when 233 then # line 527 "lib/parser/lexer.rl" begin @te = p+1 begin # Sit at EOF indefinitely. #advance would return $eof each time. # This allows to feed the lexer more data if needed; this is only used # in tests. # # Note that this action is not embedded into e_eof like e_heredoc_nl and e_bs # below. This is due to the fact that scanner state at EOF is observed # by tests, and encapsulating it in a rule would break the introspection. p = p - 1; begin p += 1 _goto_level = _out next end end end when 245 then # line 1452 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tCONSTANT) @cs = (arg_or_cmdarg(cmd_state)); begin p += 1 _goto_level = _out next end end end when 236 then # line 1456 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tIDENTIFIER) @cs = (arg_or_cmdarg(cmd_state)); begin p += 1 _goto_level = _out next end end end when 241 then # line 1467 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit_table(PUNCTUATION) @cs = 474; begin p += 1 _goto_level = _out next end end end when 239 then # line 1470 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 244 then # line 1473 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = p - 1; begin @cs = 781 _goto_level = _again next end end end when 268 then # line 1533 "lib/parser/lexer.rl" begin @te = p+1 begin # Unlike expr_beg as invoked in the next rule, do not warn p = @ts - 1 begin @cs = 781 _goto_level = _again next end end end when 251 then # line 1551 "lib/parser/lexer.rl" begin @te = p+1 begin if tok(tm, tm + 1) == '/'.freeze # Ambiguous regexp literal. if @version < 30 diagnostic :warning, :ambiguous_literal, nil, range(tm, tm + 1) else diagnostic :warning, :ambiguous_regexp, nil, range(tm, tm + 1) end end p = tm - 1 begin @cs = 543 _goto_level = _again next end end end when 257 then # line 1579 "lib/parser/lexer.rl" begin @te = p+1 begin p = p - 1; p = p - 1; begin @cs = 543 _goto_level = _again next end end end when 24 then # line 1587 "lib/parser/lexer.rl" begin @te = p+1 begin p = @ts - 1; begin @cs = 543 _goto_level = _again next end end end when 259 then # line 1596 "lib/parser/lexer.rl" begin @te = p+1 begin p = tm - 1; begin @cs = 781 _goto_level = _again next end end end when 39 then # line 1607 "lib/parser/lexer.rl" begin @te = p+1 begin p = @ts - 1 begin @cs = 781 _goto_level = _again next end end end when 246 then # line 1621 "lib/parser/lexer.rl" begin @te = p+1 begin p = p - 1; begin @cs = 543 _goto_level = _again next end end end when 247 then # line 527 "lib/parser/lexer.rl" begin @te = p+1 begin # Sit at EOF indefinitely. #advance would return $eof each time. # This allows to feed the lexer more data if needed; this is only used # in tests. # # Note that this action is not embedded into e_eof like e_heredoc_nl and e_bs # below. This is due to the fact that scanner state at EOF is observed # by tests, and encapsulating it in a rule would break the introspection. p = p - 1; begin p += 1 _goto_level = _out next end end end when 258 then # line 1542 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = p - 1; begin @cs = 543 _goto_level = _again next end end end when 254 then # line 1568 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin diagnostic :warning, :ambiguous_prefix, { :prefix => tok(tm, @te) }, range(tm, @te) p = tm - 1 begin @cs = 543 _goto_level = _again next end end end when 256 then # line 1584 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = p - 1; begin @cs = 543 _goto_level = _again next end end end when 250 then # line 1607 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = @ts - 1 begin @cs = 781 _goto_level = _again next end end end when 249 then # line 1612 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 267 then # line 1621 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = p - 1; begin @cs = 543 _goto_level = _again next end end end when 25 then # line 1612 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end end when 41 then # line 1621 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin p = p - 1; begin @cs = 543 _goto_level = _again next end end end when 23 then # line 1 "NONE" begin case @act when 71 then begin begin p = (( @te))-1; end if tok(tm, tm + 1) == '/'.freeze # Ambiguous regexp literal. if @version < 30 diagnostic :warning, :ambiguous_literal, nil, range(tm, tm + 1) else diagnostic :warning, :ambiguous_regexp, nil, range(tm, tm + 1) end end p = tm - 1 begin @cs = 543 _goto_level = _again next end end when 72 then begin begin p = (( @te))-1; end diagnostic :warning, :ambiguous_prefix, { :prefix => tok(tm, @te) }, range(tm, @te) p = tm - 1 begin @cs = 543 _goto_level = _again next end end when 77 then begin begin p = (( @te))-1; end p = @ts - 1 begin @cs = 781 _goto_level = _again next end end else begin begin p = (( @te))-1; end end end end when 43 then # line 1657 "lib/parser/lexer.rl" begin @te = p+1 begin p = @ts - 1 begin @cs = 474 _goto_level = _again next end end end when 272 then # line 527 "lib/parser/lexer.rl" begin @te = p+1 begin # Sit at EOF indefinitely. #advance would return $eof each time. # This allows to feed the lexer more data if needed; this is only used # in tests. # # Note that this action is not embedded into e_eof like e_heredoc_nl and e_bs # below. This is due to the fact that scanner state at EOF is observed # by tests, and encapsulating it in a rule would break the introspection. p = p - 1; begin p += 1 _goto_level = _out next end end end when 273 then # line 1657 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = @ts - 1 begin @cs = 474 _goto_level = _again next end end end when 44 then # line 1657 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin p = @ts - 1 begin @cs = 474 _goto_level = _again next end end end when 42 then # line 1 "NONE" begin case @act when 84 then begin begin p = (( @te))-1; end if @cond.active? emit(:kDO_COND, 'do'.freeze, @te - 2, @te) else emit(:kDO, 'do'.freeze, @te - 2, @te) end @cs = 773; begin p += 1 _goto_level = _out next end end when 85 then begin begin p = (( @te))-1; end p = @ts - 1 begin @cs = 474 _goto_level = _again next end end end end when 283 then # line 1693 "lib/parser/lexer.rl" begin @te = p+1 begin emit_do(true) @cs = 773; begin p += 1 _goto_level = _out next end end end when 276 then # line 1699 "lib/parser/lexer.rl" begin @te = p+1 begin p = p - 1; begin @cs = 781 _goto_level = _again next end end end when 277 then # line 527 "lib/parser/lexer.rl" begin @te = p+1 begin # Sit at EOF indefinitely. #advance would return $eof each time. # This allows to feed the lexer more data if needed; this is only used # in tests. # # Note that this action is not embedded into e_eof like e_heredoc_nl and e_bs # below. This is due to the fact that scanner state at EOF is observed # by tests, and encapsulating it in a rule would break the introspection. p = p - 1; begin p += 1 _goto_level = _out next end end end when 278 then # line 1696 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 281 then # line 1699 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = p - 1; begin @cs = 781 _goto_level = _again next end end end when 287 then # line 1723 "lib/parser/lexer.rl" begin @te = p+1 begin p = p - 1; begin @cs = 543 _goto_level = _again next end end end when 286 then # line 527 "lib/parser/lexer.rl" begin @te = p+1 begin # Sit at EOF indefinitely. #advance would return $eof each time. # This allows to feed the lexer more data if needed; this is only used # in tests. # # Note that this action is not embedded into e_eof like e_heredoc_nl and e_bs # below. This is due to the fact that scanner state at EOF is observed # by tests, and encapsulating it in a rule would break the introspection. p = p - 1; begin p += 1 _goto_level = _out next end end end when 295 then # line 1715 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = @ts - 1; begin @cs = 543 _goto_level = _again next end end end when 289 then # line 1717 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 293 then # line 1723 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = p - 1; begin @cs = 543 _goto_level = _again next end end end when 288 then # line 1 "NONE" begin case @act when 92 then begin begin p = (( @te))-1; end emit_table(KEYWORDS) @cs = 543; begin p += 1 _goto_level = _out next end end when 93 then begin begin p = (( @te))-1; end p = @ts - 1; begin @cs = 543 _goto_level = _again next end end end end when 56 then # line 1738 "lib/parser/lexer.rl" begin @te = p+1 begin emit(:tUNARY_NUM, tok(@ts, @ts + 1), @ts, @ts + 1) p = p - 1; @cs = 781; begin p += 1 _goto_level = _out next end end end when 328 then # line 1755 "lib/parser/lexer.rl" begin @te = p+1 begin type = delimiter = tok[0].chr p = p - 1; begin @cs = (push_literal(type, delimiter, @ts)) _goto_level = _again next end end end when 320 then # line 1762 "lib/parser/lexer.rl" begin @te = p+1 begin type, delimiter = @source_buffer.slice(@ts).chr, tok[-1].chr begin @cs = (push_literal(type, delimiter, @ts)) _goto_level = _again next end end end when 54 then # line 1769 "lib/parser/lexer.rl" begin @te = p+1 begin type, delimiter = tok[0..-2], tok[-1].chr begin @cs = (push_literal(type, delimiter, @ts)) _goto_level = _again next end end end when 341 then # line 1844 "lib/parser/lexer.rl" begin @te = p+1 begin p = p - 1; p = p - 1; emit(:tSYMBEG, tok(@ts, @ts + 1), @ts, @ts + 1) begin @cs = 333 _goto_level = _again next end end end when 329 then # line 1852 "lib/parser/lexer.rl" begin @te = p+1 begin type, delimiter = tok, tok[-1].chr begin @cs = (push_literal(type, delimiter, @ts)) _goto_level = _again next end end end when 340 then # line 1860 "lib/parser/lexer.rl" begin @te = p+1 begin emit(:tSYMBOL, tok(@ts + 1, @ts + 2)) @cs = 781; begin p += 1 _goto_level = _out next end end end when 68 then # line 1874 "lib/parser/lexer.rl" begin @te = p+1 begin emit(:tSYMBOL, tok(@ts + 1), @ts) @cs = 781; begin p += 1 _goto_level = _out next end end end when 351 then # line 1915 "lib/parser/lexer.rl" begin @te = p+1 begin escape = { " " => '\s', "\r" => '\r', "\n" => '\n', "\t" => '\t', "\v" => '\v', "\f" => '\f' }[@source_buffer.slice(@ts + 1)] diagnostic :warning, :invalid_escape_use, { :escape => escape }, range p = @ts - 1 begin @cs = 781 _goto_level = _again next end end end when 350 then # line 1925 "lib/parser/lexer.rl" begin @te = p+1 begin diagnostic :fatal, :incomplete_escape, nil, range(@ts, @ts + 1) end end when 330 then # line 1984 "lib/parser/lexer.rl" begin @te = p+1 begin emit_table(PUNCTUATION_BEGIN) begin p += 1 _goto_level = _out next end end end when 51 then # line 2005 "lib/parser/lexer.rl" begin @te = p+1 begin p = p - 1; if version?(18) ident = tok(@ts, @te - 2) emit((@source_buffer.slice(@ts) =~ /[A-Z]/) ? :tCONSTANT : :tIDENTIFIER, ident, @ts, @te - 2) p = p - 1; # continue as a symbol if !@static_env.nil? && @static_env.declared?(ident) @cs = 781; else @cs = (arg_or_cmdarg(cmd_state)); end else emit(:tLABEL, tok(@ts, @te - 2), @ts, @te - 1) @cs = 766; end begin p += 1 _goto_level = _out next end end end when 327 then # line 2043 "lib/parser/lexer.rl" begin @te = p+1 begin if @version >= 30 if @lambda_stack.any? && @lambda_stack.last + 1 == @paren_nest # To reject `->(...)` like `->...` emit(:tDOT3) else emit(:tBDOT3) end elsif @version >= 27 emit(:tBDOT3) else emit(:tDOT3) end @cs = 543; begin p += 1 _goto_level = _out next end end end when 48 then # line 2079 "lib/parser/lexer.rl" begin @te = p+1 begin emit(:tIDENTIFIER, ident_tok, ident_ts, ident_te) p = ident_te - 1 if !@static_env.nil? && @static_env.declared?(ident_tok) && @version < 25 @cs = 446; else @cs = 505; end begin p += 1 _goto_level = _out next end end end when 314 then # line 2098 "lib/parser/lexer.rl" begin @te = p+1 begin p = @ts - 1 @cs_before_block_comment = @cs begin @cs = 185 _goto_level = _again next end end end when 55 then # line 2114 "lib/parser/lexer.rl" begin @te = p+1 begin p = @ts - 1; begin @cs = 781 _goto_level = _again next end end end when 298 then # line 527 "lib/parser/lexer.rl" begin @te = p+1 begin # Sit at EOF indefinitely. #advance would return $eof each time. # This allows to feed the lexer more data if needed; this is only used # in tests. # # Note that this action is not embedded into e_eof like e_heredoc_nl and e_bs # below. This is due to the fact that scanner state at EOF is observed # by tests, and encapsulating it in a rule would break the introspection. p = p - 1; begin p += 1 _goto_level = _out next end end end when 325 then # line 1738 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tUNARY_NUM, tok(@ts, @ts + 1), @ts, @ts + 1) p = p - 1; @cs = 781; begin p += 1 _goto_level = _out next end end end when 324 then # line 1745 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tSTAR, '*'.freeze) begin p += 1 _goto_level = _out next end end end when 321 then # line 1769 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin type, delimiter = tok[0..-2], tok[-1].chr begin @cs = (push_literal(type, delimiter, @ts)) _goto_level = _again next end end end when 319 then # line 1775 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin diagnostic :fatal, :string_eof, nil, range(@ts, @ts + 1) end end when 348 then # line 1835 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin diagnostic :error, :unterminated_heredoc_id, nil, range(@ts, @ts + 1) end end when 331 then # line 1874 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tSYMBOL, tok(@ts + 1), @ts) @cs = 781; begin p += 1 _goto_level = _out next end end end when 344 then # line 1882 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin if @version >= 27 diagnostic :error, diag_msg, { name: tok(tm, @te) }, range(tm, @te) else emit(:tCOLON, tok(@ts, @ts + 1), @ts, @ts + 1) p = @ts end @cs = 781; begin p += 1 _goto_level = _out next end end end when 349 then # line 1925 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin diagnostic :fatal, :incomplete_escape, nil, range(@ts, @ts + 1) end end when 355 then # line 1931 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = @ts - 1 begin @cs = 781 _goto_level = _again next end end end when 322 then # line 1984 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit_table(PUNCTUATION_BEGIN) begin p += 1 _goto_level = _out next end end end when 326 then # line 2032 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin if @version >= 27 emit(:tBDOT2) else emit(:tDOT2) end @cs = 543; begin p += 1 _goto_level = _out next end end end when 301 then # line 1320 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tIDENTIFIER) if !@static_env.nil? && @static_env.declared?(tok) @cs = 446; begin p += 1 _goto_level = _out next end else @cs = (arg_or_cmdarg(cmd_state)); begin p += 1 _goto_level = _out next end end end end when 311 then # line 2095 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 313 then # line 2098 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = @ts - 1 @cs_before_block_comment = @cs begin @cs = 185 _goto_level = _again next end end end when 316 then # line 2114 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = @ts - 1; begin @cs = 781 _goto_level = _again next end end end when 53 then # line 1775 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin diagnostic :fatal, :string_eof, nil, range(@ts, @ts + 1) end end when 72 then # line 1835 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin diagnostic :error, :unterminated_heredoc_id, nil, range(@ts, @ts + 1) end end when 73 then # line 1902 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 47 then # line 1320 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin emit(:tIDENTIFIER) if !@static_env.nil? && @static_env.declared?(tok) @cs = 446; begin p += 1 _goto_level = _out next end else @cs = (arg_or_cmdarg(cmd_state)); begin p += 1 _goto_level = _out next end end end end when 52 then # line 2095 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end end when 67 then # line 2114 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin p = @ts - 1; begin @cs = 781 _goto_level = _again next end end end when 50 then # line 1 "NONE" begin case @act when 98 then begin begin p = (( @te))-1; end emit(:tUNARY_NUM, tok(@ts, @ts + 1), @ts, @ts + 1) p = p - 1; @cs = 781; begin p += 1 _goto_level = _out next end end when 105 then begin begin p = (( @te))-1; end diagnostic :error, :unterminated_heredoc_id, nil, range(@ts, @ts + 1) end when 116 then begin begin p = (( @te))-1; end if @version >= 27 emit(:tPIPE, tok(@ts, @ts + 1), @ts, @ts + 1) p = p - 1; @cs = 543; begin p += 1 _goto_level = _out next end else p -= 2 begin @cs = 781 _goto_level = _again next end end end when 120 then begin begin p = (( @te))-1; end emit_table(PUNCTUATION_BEGIN) begin p += 1 _goto_level = _out next end end when 121 then begin begin p = (( @te))-1; end emit(:kRESCUE, 'rescue'.freeze, @ts, tm) p = tm - 1 @cs = 519; begin p += 1 _goto_level = _out next end end when 122 then begin begin p = (( @te))-1; end emit_table(KEYWORDS_BEGIN) @command_start = true @cs = 773; begin p += 1 _goto_level = _out next end end when 126 then begin begin p = (( @te))-1; end p = @ts - 1 begin @cs = 781 _goto_level = _again next end end when 127 then begin begin p = (( @te))-1; end emit(:tIDENTIFIER) if !@static_env.nil? && @static_env.declared?(tok) @cs = 446; begin p += 1 _goto_level = _out next end else @cs = (arg_or_cmdarg(cmd_state)); begin p += 1 _goto_level = _out next end end end when 131 then begin begin p = (( @te))-1; end p = @ts - 1; begin @cs = 781 _goto_level = _again next end end end end when 386 then # line 2134 "lib/parser/lexer.rl" begin @te = p+1 begin p = p - 1; begin @cs = 543 _goto_level = _again next end end end when 387 then # line 527 "lib/parser/lexer.rl" begin @te = p+1 begin # Sit at EOF indefinitely. #advance would return $eof each time. # This allows to feed the lexer more data if needed; this is only used # in tests. # # Note that this action is not embedded into e_eof like e_heredoc_nl and e_bs # below. This is due to the fact that scanner state at EOF is observed # by tests, and encapsulating it in a rule would break the introspection. p = p - 1; begin p += 1 _goto_level = _out next end end end when 388 then # line 2122 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 392 then # line 2134 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = p - 1; begin @cs = 543 _goto_level = _again next end end end when 76 then # line 2144 "lib/parser/lexer.rl" begin @te = p+1 begin p = @ts - 1 begin @cs = 781 _goto_level = _again next end end end when 396 then # line 2149 "lib/parser/lexer.rl" begin @te = p+1 begin begin @cs = (push_literal(tok, tok, @ts)) _goto_level = _again next end end end when 395 then # line 2159 "lib/parser/lexer.rl" begin @te = p+1 begin p = p - 1; begin @cs = 543 _goto_level = _again next end end end when 394 then # line 527 "lib/parser/lexer.rl" begin @te = p+1 begin # Sit at EOF indefinitely. #advance would return $eof each time. # This allows to feed the lexer more data if needed; this is only used # in tests. # # Note that this action is not embedded into e_eof like e_heredoc_nl and e_bs # below. This is due to the fact that scanner state at EOF is observed # by tests, and encapsulating it in a rule would break the introspection. p = p - 1; begin p += 1 _goto_level = _out next end end end when 398 then # line 2153 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 397 then # line 2159 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = p - 1; begin @cs = 543 _goto_level = _again next end end end when 75 then # line 2159 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin p = p - 1; begin @cs = 543 _goto_level = _again next end end end when 431 then # line 2170 "lib/parser/lexer.rl" begin @te = p+1 begin emit(:tLAMBDA, '->'.freeze, @ts, @ts + 2) @lambda_stack.push @paren_nest @cs = 446; begin p += 1 _goto_level = _out next end end end when 85 then # line 2211 "lib/parser/lexer.rl" begin @te = p+1 begin emit(:kCLASS, 'class'.freeze, @ts, @ts + 5) emit(:tLSHFT, '<<'.freeze, @te - 2, @te) @cs = 773; begin p += 1 _goto_level = _out next end end end when 406 then # line 2347 "lib/parser/lexer.rl" begin @te = p+1 begin type, delimiter = tok, tok[-1].chr begin @cs = (push_literal(type, delimiter, @ts, nil, false, false, true)) _goto_level = _again next end end end when 78 then # line 2365 "lib/parser/lexer.rl" begin @te = p+1 begin p = @ts - 1; begin @stack[ @top] = @cs @top+= 1 @cs = 328 _goto_level = _again next end end end when 427 then # line 2372 "lib/parser/lexer.rl" begin @te = p+1 begin emit_table(PUNCTUATION) @cs = 453; begin p += 1 _goto_level = _out next end end end when 480 then # line 2396 "lib/parser/lexer.rl" begin @te = p+1 begin emit_table(PUNCTUATION) @cs = 773; begin p += 1 _goto_level = _out next end end end when 420 then # line 2405 "lib/parser/lexer.rl" begin @te = p+1 begin emit_table(PUNCTUATION); @cs = 773; begin p += 1 _goto_level = _out next end end end when 425 then # line 2440 "lib/parser/lexer.rl" begin @te = p+1 begin emit(:tOP_ASGN, tok(@ts, @te - 1)) @cs = 543; begin p += 1 _goto_level = _out next end end end when 411 then # line 2444 "lib/parser/lexer.rl" begin @te = p+1 begin emit(:tEH, '?'.freeze) @cs = 773; begin p += 1 _goto_level = _out next end end end when 408 then # line 2463 "lib/parser/lexer.rl" begin @te = p+1 begin emit_table(PUNCTUATION) @cs = 543; begin p += 1 _goto_level = _out next end end end when 410 then # line 2476 "lib/parser/lexer.rl" begin @te = p+1 begin emit(:tSEMI, ';'.freeze) @command_start = true @cs = 773; begin p += 1 _goto_level = _out next end end end when 485 then # line 2480 "lib/parser/lexer.rl" begin @te = p+1 begin diagnostic :error, :bare_backslash, nil, range(@ts, @ts + 1) p = p - 1; end end when 405 then # line 2486 "lib/parser/lexer.rl" begin @te = p+1 begin diagnostic :fatal, :unexpected, { :character => tok.inspect[1..-2] } end end when 404 then # line 527 "lib/parser/lexer.rl" begin @te = p+1 begin # Sit at EOF indefinitely. #advance would return $eof each time. # This allows to feed the lexer more data if needed; this is only used # in tests. # # Note that this action is not embedded into e_eof like e_heredoc_nl and e_bs # below. This is due to the fact that scanner state at EOF is observed # by tests, and encapsulating it in a rule would break the introspection. p = p - 1; begin p += 1 _goto_level = _out next end end end when 496 then # line 2207 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit_table(KEYWORDS) @cs = 333; begin p += 1 _goto_level = _out next end end end when 494 then # line 2211 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:kCLASS, 'class'.freeze, @ts, @ts + 5) emit(:tLSHFT, '<<'.freeze, @te - 2, @te) @cs = 773; begin p += 1 _goto_level = _out next end end end when 493 then # line 2222 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit_table(KEYWORDS) @command_start = true @cs = 773; begin p += 1 _goto_level = _out next end end end when 435 then # line 2297 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin diagnostic :error, :no_dot_digit_literal end end when 482 then # line 2357 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tCONSTANT) @cs = (arg_or_cmdarg(cmd_state)); begin p += 1 _goto_level = _out next end end end when 424 then # line 2365 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = @ts - 1; begin @stack[ @top] = @cs @top+= 1 @cs = 328 _goto_level = _again next end end end when 432 then # line 2372 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit_table(PUNCTUATION) @cs = 453; begin p += 1 _goto_level = _out next end end end when 488 then # line 1320 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tIDENTIFIER) if !@static_env.nil? && @static_env.declared?(tok) @cs = 446; begin p += 1 _goto_level = _out next end else @cs = (arg_or_cmdarg(cmd_state)); begin p += 1 _goto_level = _out next end end end end when 430 then # line 2396 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit_table(PUNCTUATION) @cs = 773; begin p += 1 _goto_level = _out next end end end when 426 then # line 2405 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit_table(PUNCTUATION); @cs = 773; begin p += 1 _goto_level = _out next end end end when 419 then # line 2411 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit_table(PUNCTUATION) @cs = 543; begin p += 1 _goto_level = _out next end end end when 433 then # line 2463 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit_table(PUNCTUATION) @cs = 543; begin p += 1 _goto_level = _out next end end end when 417 then # line 2470 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 423 then # line 2486 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin diagnostic :fatal, :unexpected, { :character => tok.inspect[1..-2] } end end when 83 then # line 2270 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin digits = tok(@num_digits_s, @num_suffix_s) if digits.end_with? '_'.freeze diagnostic :error, :trailing_in_number, { :character => '_'.freeze }, range(@te - 1, @te) elsif digits.empty? && @num_base == 8 && version?(18) # 1.8 did not raise an error on 0o. digits = '0'.freeze elsif digits.empty? diagnostic :error, :empty_numeric elsif @num_base == 8 && (invalid_idx = digits.index(/[89]/)) invalid_s = @num_digits_s + invalid_idx diagnostic :error, :invalid_octal, nil, range(invalid_s, invalid_s + 1) end if version?(18, 19, 20) emit(:tINTEGER, digits.to_i(@num_base), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits.to_i(@num_base)) end begin p += 1 _goto_level = _out next end end end when 79 then # line 2297 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin diagnostic :error, :no_dot_digit_literal end end when 82 then # line 2329 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin digits = tok(@ts, @num_suffix_s) if version?(18, 19, 20) emit(:tFLOAT, Float(digits), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits) end begin p += 1 _goto_level = _out next end end end when 77 then # line 2486 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin diagnostic :fatal, :unexpected, { :character => tok.inspect[1..-2] } end end when 80 then # line 1 "NONE" begin case @act when 144 then begin begin p = (( @te))-1; end if @lambda_stack.last == @paren_nest @lambda_stack.pop if tok == '{'.freeze emit(:tLAMBEG, '{'.freeze) else # 'do' emit(:kDO_LAMBDA, 'do'.freeze) end else if tok == '{'.freeze emit(:tLCURLY, '{'.freeze) else # 'do' emit_do end end if tok == '{'.freeze @paren_nest += 1 end @command_start = true @cs = 773; begin p += 1 _goto_level = _out next end end when 145 then begin begin p = (( @te))-1; end emit_table(KEYWORDS) @cs = 333; begin p += 1 _goto_level = _out next end end when 146 then begin begin p = (( @te))-1; end emit(:kCLASS, 'class'.freeze, @ts, @ts + 5) emit(:tLSHFT, '<<'.freeze, @te - 2, @te) @cs = 773; begin p += 1 _goto_level = _out next end end when 147 then begin begin p = (( @te))-1; end emit_table(KEYWORDS) @cs = 543; begin p += 1 _goto_level = _out next end end when 148 then begin begin p = (( @te))-1; end emit_table(KEYWORDS) @command_start = true @cs = 773; begin p += 1 _goto_level = _out next end end when 149 then begin begin p = (( @te))-1; end emit_table(KEYWORDS) @cs = 519; begin p += 1 _goto_level = _out next end end when 150 then begin begin p = (( @te))-1; end emit_table(KEYWORDS) if version?(18) && tok == 'not'.freeze @cs = 543; begin p += 1 _goto_level = _out next end else @cs = 474; begin p += 1 _goto_level = _out next end end end when 151 then begin begin p = (( @te))-1; end if version?(18) emit(:tIDENTIFIER) unless !@static_env.nil? && @static_env.declared?(tok) @cs = (arg_or_cmdarg(cmd_state)); end else emit(:k__ENCODING__, '__ENCODING__'.freeze) end begin p += 1 _goto_level = _out next end end when 152 then begin begin p = (( @te))-1; end emit_table(KEYWORDS) begin p += 1 _goto_level = _out next end end when 153 then begin begin p = (( @te))-1; end digits = tok(@num_digits_s, @num_suffix_s) if digits.end_with? '_'.freeze diagnostic :error, :trailing_in_number, { :character => '_'.freeze }, range(@te - 1, @te) elsif digits.empty? && @num_base == 8 && version?(18) # 1.8 did not raise an error on 0o. digits = '0'.freeze elsif digits.empty? diagnostic :error, :empty_numeric elsif @num_base == 8 && (invalid_idx = digits.index(/[89]/)) invalid_s = @num_digits_s + invalid_idx diagnostic :error, :invalid_octal, nil, range(invalid_s, invalid_s + 1) end if version?(18, 19, 20) emit(:tINTEGER, digits.to_i(@num_base), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits.to_i(@num_base)) end begin p += 1 _goto_level = _out next end end when 155 then begin begin p = (( @te))-1; end if version?(18, 19, 20) diagnostic :error, :trailing_in_number, { :character => tok(@te - 1, @te) }, range(@te - 1, @te) else emit(:tINTEGER, tok(@ts, @te - 1).to_i, @ts, @te - 1) p = p - 1; begin p += 1 _goto_level = _out next end end end when 156 then begin begin p = (( @te))-1; end if version?(18, 19, 20) diagnostic :error, :trailing_in_number, { :character => tok(@te - 1, @te) }, range(@te - 1, @te) else emit(:tFLOAT, tok(@ts, @te - 1).to_f, @ts, @te - 1) p = p - 1; begin p += 1 _goto_level = _out next end end end when 157 then begin begin p = (( @te))-1; end digits = tok(@ts, @num_suffix_s) if version?(18, 19, 20) emit(:tFLOAT, Float(digits), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits) end begin p += 1 _goto_level = _out next end end when 159 then begin begin p = (( @te))-1; end emit(:tCONSTANT) @cs = (arg_or_cmdarg(cmd_state)); begin p += 1 _goto_level = _out next end end when 163 then begin begin p = (( @te))-1; end emit(:tIDENTIFIER) if !@static_env.nil? && @static_env.declared?(tok) @cs = 446; begin p += 1 _goto_level = _out next end else @cs = (arg_or_cmdarg(cmd_state)); begin p += 1 _goto_level = _out next end end end when 164 then begin begin p = (( @te))-1; end if tm == @te # Suffix was consumed, e.g. foo! emit(:tFID) else # Suffix was not consumed, e.g. foo!= emit(:tIDENTIFIER, tok(@ts, tm), @ts, tm) p = tm - 1 end @cs = 474; begin p += 1 _goto_level = _out next end end when 166 then begin begin p = (( @te))-1; end emit_table(PUNCTUATION); @cs = 773; begin p += 1 _goto_level = _out next end end when 167 then begin begin p = (( @te))-1; end emit_table(PUNCTUATION) @cs = 543; begin p += 1 _goto_level = _out next end end end end when 95 then # line 2516 "lib/parser/lexer.rl" begin @te = p+1 begin p = tm - 1; begin @cs = 781 _goto_level = _again next end end end when 501 then # line 2519 "lib/parser/lexer.rl" begin @te = p+1 begin emit(:tNL, nil, @newline_s, @newline_s + 1) p = p - 1; @cs = 185; begin p += 1 _goto_level = _out next end end end when 504 then # line 2502 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin if @version < 27 # Ruby before 2.7 doesn't support comments before leading dot. # If a line after "a" starts with a comment then "a" is a self-contained statement. # So in that case we emit a special tNL token and start reading the # next line as a separate statement. # # Note: block comments before leading dot are not supported on any version of Ruby. emit(:tNL, nil, @newline_s, @newline_s + 1) p = p - 1; @cs = 185; begin p += 1 _goto_level = _out next end end end end when 503 then # line 2519 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tNL, nil, @newline_s, @newline_s + 1) p = p - 1; @cs = 185; begin p += 1 _goto_level = _out next end end end when 90 then # line 2502 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin if @version < 27 # Ruby before 2.7 doesn't support comments before leading dot. # If a line after "a" starts with a comment then "a" is a self-contained statement. # So in that case we emit a special tNL token and start reading the # next line as a separate statement. # # Note: block comments before leading dot are not supported on any version of Ruby. emit(:tNL, nil, @newline_s, @newline_s + 1) p = p - 1; @cs = 185; begin p += 1 _goto_level = _out next end end end end when 86 then # line 2519 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin emit(:tNL, nil, @newline_s, @newline_s + 1) p = p - 1; @cs = 185; begin p += 1 _goto_level = _out next end end end when 91 then # line 1 "NONE" begin case @act when 180 then begin begin p = (( @te))-1; end if @version < 27 # Ruby before 2.7 doesn't support comments before leading dot. # If a line after "a" starts with a comment then "a" is a self-contained statement. # So in that case we emit a special tNL token and start reading the # next line as a separate statement. # # Note: block comments before leading dot are not supported on any version of Ruby. emit(:tNL, nil, @newline_s, @newline_s + 1) p = p - 1; @cs = 185; begin p += 1 _goto_level = _out next end end end when 182 then begin begin p = (( @te))-1; end emit(:tNL, nil, @newline_s, @newline_s + 1) p = p - 1; @cs = 185; begin p += 1 _goto_level = _out next end end end end when 507 then # line 2529 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit_comment(@eq_begin_s, @te) begin @cs = (@cs_before_block_comment) _goto_level = _again next end end end when 506 then # line 2537 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin diagnostic :fatal, :embedded_document, nil, range(@eq_begin_s, @eq_begin_s + '=begin'.length) end end when 106 then # line 2547 "lib/parser/lexer.rl" begin @te = p+1 begin @eq_begin_s = @ts begin @cs = 967 _goto_level = _again next end end end when 2 then # line 2551 "lib/parser/lexer.rl" begin @te = p+1 begin p = pe - 3 end end when 98 then # line 2554 "lib/parser/lexer.rl" begin @te = p+1 begin cmd_state = true; p = p - 1; begin @cs = 773 _goto_level = _again next end end end when 99 then # line 527 "lib/parser/lexer.rl" begin @te = p+1 begin # Sit at EOF indefinitely. #advance would return $eof each time. # This allows to feed the lexer more data if needed; this is only used # in tests. # # Note that this action is not embedded into e_eof like e_heredoc_nl and e_bs # below. This is due to the fact that scanner state at EOF is observed # by tests, and encapsulating it in a rule would break the introspection. p = p - 1; begin p += 1 _goto_level = _out next end end end when 100 then # line 2544 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 105 then # line 2547 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin @eq_begin_s = @ts begin @cs = 967 _goto_level = _again next end end end when 104 then # line 2554 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin cmd_state = true; p = p - 1; begin @cs = 773 _goto_level = _again next end end end when 1 then # line 2554 "lib/parser/lexer.rl" begin begin p = (( @te))-1; end begin cmd_state = true; p = p - 1; begin @cs = 773 _goto_level = _again next end end end when 66 then # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end when 110 then # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end # line 950 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal if @te == pe diagnostic :fatal, :string_eof, nil, range(current_literal.str_s, current_literal.str_s + 1) end if current_literal.heredoc? line = tok(@herebody_s, @ts).gsub(/\r+$/, ''.freeze) if version?(18, 19, 20) # See ruby:c48b4209c line = line.gsub(/\r.*$/, ''.freeze) end # Try ending the heredoc with the complete most recently # scanned line. @herebody_s always refers to the start of such line. if current_literal.nest_and_try_closing(line, @herebody_s, @ts) # Adjust @herebody_s to point to the next line. @herebody_s = @te # Continue regular lexing after the heredoc reference (<<END). p = current_literal.heredoc_e - 1 @cs = (pop_literal); begin p += 1 _goto_level = _out next end else # Calculate indentation level for <<~HEREDOCs. current_literal.infer_indent_level(line) # Ditto. @herebody_s = @te end else # Try ending the literal with a newline. if current_literal.nest_and_try_closing(tok, @ts, @te) @cs = (pop_literal); begin p += 1 _goto_level = _out next end end if @herebody_s # This is a regular literal intertwined with a heredoc. Like: # # p <<-foo+"1 # bar # foo # 2" # # which, incidentally, evaluates to "bar\n1\n2". p = @herebody_s - 1 @herebody_s = nil end end if current_literal.words? && !eof_codepoint?(@source_pts[p]) current_literal.extend_space @ts, @te else # A literal newline is appended if the heredoc was _not_ closed # this time (see fbreak above). See also Literal#nest_and_try_closing # for rationale of calling #flush_string here. current_literal.extend_string tok, @ts, @te current_literal.flush_string end end end when 140 then # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end # line 950 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal if @te == pe diagnostic :fatal, :string_eof, nil, range(current_literal.str_s, current_literal.str_s + 1) end if current_literal.heredoc? line = tok(@herebody_s, @ts).gsub(/\r+$/, ''.freeze) if version?(18, 19, 20) # See ruby:c48b4209c line = line.gsub(/\r.*$/, ''.freeze) end # Try ending the heredoc with the complete most recently # scanned line. @herebody_s always refers to the start of such line. if current_literal.nest_and_try_closing(line, @herebody_s, @ts) # Adjust @herebody_s to point to the next line. @herebody_s = @te # Continue regular lexing after the heredoc reference (<<END). p = current_literal.heredoc_e - 1 @cs = (pop_literal); begin p += 1 _goto_level = _out next end else # Calculate indentation level for <<~HEREDOCs. current_literal.infer_indent_level(line) # Ditto. @herebody_s = @te end else # Try ending the literal with a newline. if current_literal.nest_and_try_closing(tok, @ts, @te) @cs = (pop_literal); begin p += 1 _goto_level = _out next end end if @herebody_s # This is a regular literal intertwined with a heredoc. Like: # # p <<-foo+"1 # bar # foo # 2" # # which, incidentally, evaluates to "bar\n1\n2". p = @herebody_s - 1 @herebody_s = nil end end if current_literal.words? && !eof_codepoint?(@source_pts[p]) current_literal.extend_space @ts, @te else # A literal newline is appended if the heredoc was _not_ closed # this time (see fbreak above). See also Literal#nest_and_try_closing # for rationale of calling #flush_string here. current_literal.extend_string tok, @ts, @te current_literal.flush_string end end end when 168 then # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end # line 950 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal if @te == pe diagnostic :fatal, :string_eof, nil, range(current_literal.str_s, current_literal.str_s + 1) end if current_literal.heredoc? line = tok(@herebody_s, @ts).gsub(/\r+$/, ''.freeze) if version?(18, 19, 20) # See ruby:c48b4209c line = line.gsub(/\r.*$/, ''.freeze) end # Try ending the heredoc with the complete most recently # scanned line. @herebody_s always refers to the start of such line. if current_literal.nest_and_try_closing(line, @herebody_s, @ts) # Adjust @herebody_s to point to the next line. @herebody_s = @te # Continue regular lexing after the heredoc reference (<<END). p = current_literal.heredoc_e - 1 @cs = (pop_literal); begin p += 1 _goto_level = _out next end else # Calculate indentation level for <<~HEREDOCs. current_literal.infer_indent_level(line) # Ditto. @herebody_s = @te end else # Try ending the literal with a newline. if current_literal.nest_and_try_closing(tok, @ts, @te) @cs = (pop_literal); begin p += 1 _goto_level = _out next end end if @herebody_s # This is a regular literal intertwined with a heredoc. Like: # # p <<-foo+"1 # bar # foo # 2" # # which, incidentally, evaluates to "bar\n1\n2". p = @herebody_s - 1 @herebody_s = nil end end if current_literal.words? && !eof_codepoint?(@source_pts[p]) current_literal.extend_space @ts, @te else # A literal newline is appended if the heredoc was _not_ closed # this time (see fbreak above). See also Literal#nest_and_try_closing # for rationale of calling #flush_string here. current_literal.extend_string tok, @ts, @te current_literal.flush_string end end end when 174 then # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end # line 950 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal if @te == pe diagnostic :fatal, :string_eof, nil, range(current_literal.str_s, current_literal.str_s + 1) end if current_literal.heredoc? line = tok(@herebody_s, @ts).gsub(/\r+$/, ''.freeze) if version?(18, 19, 20) # See ruby:c48b4209c line = line.gsub(/\r.*$/, ''.freeze) end # Try ending the heredoc with the complete most recently # scanned line. @herebody_s always refers to the start of such line. if current_literal.nest_and_try_closing(line, @herebody_s, @ts) # Adjust @herebody_s to point to the next line. @herebody_s = @te # Continue regular lexing after the heredoc reference (<<END). p = current_literal.heredoc_e - 1 @cs = (pop_literal); begin p += 1 _goto_level = _out next end else # Calculate indentation level for <<~HEREDOCs. current_literal.infer_indent_level(line) # Ditto. @herebody_s = @te end else # Try ending the literal with a newline. if current_literal.nest_and_try_closing(tok, @ts, @te) @cs = (pop_literal); begin p += 1 _goto_level = _out next end end if @herebody_s # This is a regular literal intertwined with a heredoc. Like: # # p <<-foo+"1 # bar # foo # 2" # # which, incidentally, evaluates to "bar\n1\n2". p = @herebody_s - 1 @herebody_s = nil end end if current_literal.words? && !eof_codepoint?(@source_pts[p]) current_literal.extend_space @ts, @te else # A literal newline is appended if the heredoc was _not_ closed # this time (see fbreak above). See also Literal#nest_and_try_closing # for rationale of calling #flush_string here. current_literal.extend_string tok, @ts, @te current_literal.flush_string end end end when 180 then # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end # line 950 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal if @te == pe diagnostic :fatal, :string_eof, nil, range(current_literal.str_s, current_literal.str_s + 1) end if current_literal.heredoc? line = tok(@herebody_s, @ts).gsub(/\r+$/, ''.freeze) if version?(18, 19, 20) # See ruby:c48b4209c line = line.gsub(/\r.*$/, ''.freeze) end # Try ending the heredoc with the complete most recently # scanned line. @herebody_s always refers to the start of such line. if current_literal.nest_and_try_closing(line, @herebody_s, @ts) # Adjust @herebody_s to point to the next line. @herebody_s = @te # Continue regular lexing after the heredoc reference (<<END). p = current_literal.heredoc_e - 1 @cs = (pop_literal); begin p += 1 _goto_level = _out next end else # Calculate indentation level for <<~HEREDOCs. current_literal.infer_indent_level(line) # Ditto. @herebody_s = @te end else # Try ending the literal with a newline. if current_literal.nest_and_try_closing(tok, @ts, @te) @cs = (pop_literal); begin p += 1 _goto_level = _out next end end if @herebody_s # This is a regular literal intertwined with a heredoc. Like: # # p <<-foo+"1 # bar # foo # 2" # # which, incidentally, evaluates to "bar\n1\n2". p = @herebody_s - 1 @herebody_s = nil end end if current_literal.words? && !eof_codepoint?(@source_pts[p]) current_literal.extend_space @ts, @te else # A literal newline is appended if the heredoc was _not_ closed # this time (see fbreak above). See also Literal#nest_and_try_closing # for rationale of calling #flush_string here. current_literal.extend_string tok, @ts, @te current_literal.flush_string end end end when 187 then # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end # line 950 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal if @te == pe diagnostic :fatal, :string_eof, nil, range(current_literal.str_s, current_literal.str_s + 1) end if current_literal.heredoc? line = tok(@herebody_s, @ts).gsub(/\r+$/, ''.freeze) if version?(18, 19, 20) # See ruby:c48b4209c line = line.gsub(/\r.*$/, ''.freeze) end # Try ending the heredoc with the complete most recently # scanned line. @herebody_s always refers to the start of such line. if current_literal.nest_and_try_closing(line, @herebody_s, @ts) # Adjust @herebody_s to point to the next line. @herebody_s = @te # Continue regular lexing after the heredoc reference (<<END). p = current_literal.heredoc_e - 1 @cs = (pop_literal); begin p += 1 _goto_level = _out next end else # Calculate indentation level for <<~HEREDOCs. current_literal.infer_indent_level(line) # Ditto. @herebody_s = @te end else # Try ending the literal with a newline. if current_literal.nest_and_try_closing(tok, @ts, @te) @cs = (pop_literal); begin p += 1 _goto_level = _out next end end if @herebody_s # This is a regular literal intertwined with a heredoc. Like: # # p <<-foo+"1 # bar # foo # 2" # # which, incidentally, evaluates to "bar\n1\n2". p = @herebody_s - 1 @herebody_s = nil end end if current_literal.words? && !eof_codepoint?(@source_pts[p]) current_literal.extend_space @ts, @te else # A literal newline is appended if the heredoc was _not_ closed # this time (see fbreak above). See also Literal#nest_and_try_closing # for rationale of calling #flush_string here. current_literal.extend_string tok, @ts, @te current_literal.flush_string end end end when 190 then # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end # line 950 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal if @te == pe diagnostic :fatal, :string_eof, nil, range(current_literal.str_s, current_literal.str_s + 1) end if current_literal.heredoc? line = tok(@herebody_s, @ts).gsub(/\r+$/, ''.freeze) if version?(18, 19, 20) # See ruby:c48b4209c line = line.gsub(/\r.*$/, ''.freeze) end # Try ending the heredoc with the complete most recently # scanned line. @herebody_s always refers to the start of such line. if current_literal.nest_and_try_closing(line, @herebody_s, @ts) # Adjust @herebody_s to point to the next line. @herebody_s = @te # Continue regular lexing after the heredoc reference (<<END). p = current_literal.heredoc_e - 1 @cs = (pop_literal); begin p += 1 _goto_level = _out next end else # Calculate indentation level for <<~HEREDOCs. current_literal.infer_indent_level(line) # Ditto. @herebody_s = @te end else # Try ending the literal with a newline. if current_literal.nest_and_try_closing(tok, @ts, @te) @cs = (pop_literal); begin p += 1 _goto_level = _out next end end if @herebody_s # This is a regular literal intertwined with a heredoc. Like: # # p <<-foo+"1 # bar # foo # 2" # # which, incidentally, evaluates to "bar\n1\n2". p = @herebody_s - 1 @herebody_s = nil end end if current_literal.words? && !eof_codepoint?(@source_pts[p]) current_literal.extend_space @ts, @te else # A literal newline is appended if the heredoc was _not_ closed # this time (see fbreak above). See also Literal#nest_and_try_closing # for rationale of calling #flush_string here. current_literal.extend_string tok, @ts, @te current_literal.flush_string end end end when 198 then # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end # line 950 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal if @te == pe diagnostic :fatal, :string_eof, nil, range(current_literal.str_s, current_literal.str_s + 1) end if current_literal.heredoc? line = tok(@herebody_s, @ts).gsub(/\r+$/, ''.freeze) if version?(18, 19, 20) # See ruby:c48b4209c line = line.gsub(/\r.*$/, ''.freeze) end # Try ending the heredoc with the complete most recently # scanned line. @herebody_s always refers to the start of such line. if current_literal.nest_and_try_closing(line, @herebody_s, @ts) # Adjust @herebody_s to point to the next line. @herebody_s = @te # Continue regular lexing after the heredoc reference (<<END). p = current_literal.heredoc_e - 1 @cs = (pop_literal); begin p += 1 _goto_level = _out next end else # Calculate indentation level for <<~HEREDOCs. current_literal.infer_indent_level(line) # Ditto. @herebody_s = @te end else # Try ending the literal with a newline. if current_literal.nest_and_try_closing(tok, @ts, @te) @cs = (pop_literal); begin p += 1 _goto_level = _out next end end if @herebody_s # This is a regular literal intertwined with a heredoc. Like: # # p <<-foo+"1 # bar # foo # 2" # # which, incidentally, evaluates to "bar\n1\n2". p = @herebody_s - 1 @herebody_s = nil end end if current_literal.words? && !eof_codepoint?(@source_pts[p]) current_literal.extend_space @ts, @te else # A literal newline is appended if the heredoc was _not_ closed # this time (see fbreak above). See also Literal#nest_and_try_closing # for rationale of calling #flush_string here. current_literal.extend_string tok, @ts, @te current_literal.flush_string end end end when 269 then # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end # line 1533 "lib/parser/lexer.rl" begin @te = p+1 begin # Unlike expr_beg as invoked in the next rule, do not warn p = @ts - 1 begin @cs = 781 _goto_level = _again next end end end when 260 then # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end # line 1596 "lib/parser/lexer.rl" begin @te = p+1 begin p = tm - 1; begin @cs = 781 _goto_level = _again next end end end when 252 then # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end # line 1607 "lib/parser/lexer.rl" begin @te = p+1 begin p = @ts - 1 begin @cs = 781 _goto_level = _again next end end end when 352 then # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end # line 1915 "lib/parser/lexer.rl" begin @te = p+1 begin escape = { " " => '\s', "\r" => '\r', "\n" => '\n', "\t" => '\t', "\v" => '\v', "\f" => '\f' }[@source_buffer.slice(@ts + 1)] diagnostic :warning, :invalid_escape_use, { :escape => escape }, range p = @ts - 1 begin @cs = 781 _goto_level = _again next end end end when 315 then # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end # line 2098 "lib/parser/lexer.rl" begin @te = p+1 begin p = @ts - 1 @cs_before_block_comment = @cs begin @cs = 185 _goto_level = _again next end end end when 434 then # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end # line 2452 "lib/parser/lexer.rl" begin @te = p+1 begin if @paren_nest == 0 diagnostic :warning, :triple_dot_at_eol, nil, range(@ts, @te - 1) end emit(:tDOT3, '...'.freeze, @ts, @te - 1) p = p - 1; @cs = 543; begin p += 1 _goto_level = _out next end end end when 508 then # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end # line 2529 "lib/parser/lexer.rl" begin @te = p+1 begin emit_comment(@eq_begin_s, @te) begin @cs = (@cs_before_block_comment) _goto_level = _again next end end end when 505 then # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end # line 2534 "lib/parser/lexer.rl" begin @te = p+1 end when 107 then # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end # line 2547 "lib/parser/lexer.rl" begin @te = p+1 begin @eq_begin_s = @ts begin @cs = 967 _goto_level = _again next end end end when 3 then # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end # line 2551 "lib/parser/lexer.rl" begin @te = p+1 begin p = pe - 3 end end when 456 then # line 635 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tRATIONAL, Rational(chars)) } end # line 2270 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin digits = tok(@num_digits_s, @num_suffix_s) if digits.end_with? '_'.freeze diagnostic :error, :trailing_in_number, { :character => '_'.freeze }, range(@te - 1, @te) elsif digits.empty? && @num_base == 8 && version?(18) # 1.8 did not raise an error on 0o. digits = '0'.freeze elsif digits.empty? diagnostic :error, :empty_numeric elsif @num_base == 8 && (invalid_idx = digits.index(/[89]/)) invalid_s = @num_digits_s + invalid_idx diagnostic :error, :invalid_octal, nil, range(invalid_s, invalid_s + 1) end if version?(18, 19, 20) emit(:tINTEGER, digits.to_i(@num_base), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits.to_i(@num_base)) end begin p += 1 _goto_level = _out next end end end when 454 then # line 636 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tIMAGINARY, Complex(0, chars)) } end # line 2270 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin digits = tok(@num_digits_s, @num_suffix_s) if digits.end_with? '_'.freeze diagnostic :error, :trailing_in_number, { :character => '_'.freeze }, range(@te - 1, @te) elsif digits.empty? && @num_base == 8 && version?(18) # 1.8 did not raise an error on 0o. digits = '0'.freeze elsif digits.empty? diagnostic :error, :empty_numeric elsif @num_base == 8 && (invalid_idx = digits.index(/[89]/)) invalid_s = @num_digits_s + invalid_idx diagnostic :error, :invalid_octal, nil, range(invalid_s, invalid_s + 1) end if version?(18, 19, 20) emit(:tINTEGER, digits.to_i(@num_base), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits.to_i(@num_base)) end begin p += 1 _goto_level = _out next end end end when 459 then # line 637 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tIMAGINARY, Complex(0, Rational(chars))) } end # line 2270 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin digits = tok(@num_digits_s, @num_suffix_s) if digits.end_with? '_'.freeze diagnostic :error, :trailing_in_number, { :character => '_'.freeze }, range(@te - 1, @te) elsif digits.empty? && @num_base == 8 && version?(18) # 1.8 did not raise an error on 0o. digits = '0'.freeze elsif digits.empty? diagnostic :error, :empty_numeric elsif @num_base == 8 && (invalid_idx = digits.index(/[89]/)) invalid_s = @num_digits_s + invalid_idx diagnostic :error, :invalid_octal, nil, range(invalid_s, invalid_s + 1) end if version?(18, 19, 20) emit(:tINTEGER, digits.to_i(@num_base), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits.to_i(@num_base)) end begin p += 1 _goto_level = _out next end end end when 457 then # line 638 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tINTEGER, chars, @ts, @te - 2); p -= 2 } end # line 2270 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin digits = tok(@num_digits_s, @num_suffix_s) if digits.end_with? '_'.freeze diagnostic :error, :trailing_in_number, { :character => '_'.freeze }, range(@te - 1, @te) elsif digits.empty? && @num_base == 8 && version?(18) # 1.8 did not raise an error on 0o. digits = '0'.freeze elsif digits.empty? diagnostic :error, :empty_numeric elsif @num_base == 8 && (invalid_idx = digits.index(/[89]/)) invalid_s = @num_digits_s + invalid_idx diagnostic :error, :invalid_octal, nil, range(invalid_s, invalid_s + 1) end if version?(18, 19, 20) emit(:tINTEGER, digits.to_i(@num_base), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits.to_i(@num_base)) end begin p += 1 _goto_level = _out next end end end when 455 then # line 639 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tINTEGER, chars, @ts, @te - 2); p -= 2 } end # line 2270 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin digits = tok(@num_digits_s, @num_suffix_s) if digits.end_with? '_'.freeze diagnostic :error, :trailing_in_number, { :character => '_'.freeze }, range(@te - 1, @te) elsif digits.empty? && @num_base == 8 && version?(18) # 1.8 did not raise an error on 0o. digits = '0'.freeze elsif digits.empty? diagnostic :error, :empty_numeric elsif @num_base == 8 && (invalid_idx = digits.index(/[89]/)) invalid_s = @num_digits_s + invalid_idx diagnostic :error, :invalid_octal, nil, range(invalid_s, invalid_s + 1) end if version?(18, 19, 20) emit(:tINTEGER, digits.to_i(@num_base), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits.to_i(@num_base)) end begin p += 1 _goto_level = _out next end end end when 458 then # line 640 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tINTEGER, chars, @ts, @te - 6); p -= 6 } end # line 2270 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin digits = tok(@num_digits_s, @num_suffix_s) if digits.end_with? '_'.freeze diagnostic :error, :trailing_in_number, { :character => '_'.freeze }, range(@te - 1, @te) elsif digits.empty? && @num_base == 8 && version?(18) # 1.8 did not raise an error on 0o. digits = '0'.freeze elsif digits.empty? diagnostic :error, :empty_numeric elsif @num_base == 8 && (invalid_idx = digits.index(/[89]/)) invalid_s = @num_digits_s + invalid_idx diagnostic :error, :invalid_octal, nil, range(invalid_s, invalid_s + 1) end if version?(18, 19, 20) emit(:tINTEGER, digits.to_i(@num_base), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits.to_i(@num_base)) end begin p += 1 _goto_level = _out next end end end when 447 then # line 644 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tIMAGINARY, Complex(0, Float(chars))) } end # line 2329 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin digits = tok(@ts, @num_suffix_s) if version?(18, 19, 20) emit(:tFLOAT, Float(digits), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits) end begin p += 1 _goto_level = _out next end end end when 448 then # line 645 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tFLOAT, Float(chars), @ts, @te - 2); p -= 2 } end # line 2329 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin digits = tok(@ts, @num_suffix_s) if version?(18, 19, 20) emit(:tFLOAT, Float(digits), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits) end begin p += 1 _goto_level = _out next end end end when 449 then # line 649 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tRATIONAL, Rational(chars)) } end # line 2329 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin digits = tok(@ts, @num_suffix_s) if version?(18, 19, 20) emit(:tFLOAT, Float(digits), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits) end begin p += 1 _goto_level = _out next end end end when 451 then # line 650 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tIMAGINARY, Complex(0, Rational(chars))) } end # line 2329 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin digits = tok(@ts, @num_suffix_s) if version?(18, 19, 20) emit(:tFLOAT, Float(digits), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits) end begin p += 1 _goto_level = _out next end end end when 450 then # line 651 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tFLOAT, Float(chars), @ts, @te - 6); p -= 6 } end # line 2329 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin digits = tok(@ts, @num_suffix_s) if version?(18, 19, 20) emit(:tFLOAT, Float(digits), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits) end begin p += 1 _goto_level = _out next end end end when 134 then # line 666 "lib/parser/lexer.rl" begin @escape = "" codepoints = tok(@escape_s + 2, p - 1) codepoint_s = @escape_s + 2 if @version < 24 if codepoints.start_with?(" ") || codepoints.start_with?("\t") diagnostic :fatal, :invalid_unicode_escape, nil, range(@escape_s + 2, @escape_s + 3) end if spaces_p = codepoints.index(/[ \t]{2}/) diagnostic :fatal, :invalid_unicode_escape, nil, range(codepoint_s + spaces_p + 1, codepoint_s + spaces_p + 2) end if codepoints.end_with?(" ") || codepoints.end_with?("\t") diagnostic :fatal, :invalid_unicode_escape, nil, range(p - 1, p) end end codepoints.scan(/([0-9a-fA-F]+)|([ \t]+)/).each do |(codepoint_str, spaces)| if spaces codepoint_s += spaces.length else codepoint = codepoint_str.to_i(16) if codepoint >= 0x110000 diagnostic :error, :unicode_point_too_large, nil, range(codepoint_s, codepoint_s + codepoint_str.length) break end @escape += codepoint.chr(Encoding::UTF_8) codepoint_s += codepoint_str.length end end end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 162 then # line 666 "lib/parser/lexer.rl" begin @escape = "" codepoints = tok(@escape_s + 2, p - 1) codepoint_s = @escape_s + 2 if @version < 24 if codepoints.start_with?(" ") || codepoints.start_with?("\t") diagnostic :fatal, :invalid_unicode_escape, nil, range(@escape_s + 2, @escape_s + 3) end if spaces_p = codepoints.index(/[ \t]{2}/) diagnostic :fatal, :invalid_unicode_escape, nil, range(codepoint_s + spaces_p + 1, codepoint_s + spaces_p + 2) end if codepoints.end_with?(" ") || codepoints.end_with?("\t") diagnostic :fatal, :invalid_unicode_escape, nil, range(p - 1, p) end end codepoints.scan(/([0-9a-fA-F]+)|([ \t]+)/).each do |(codepoint_str, spaces)| if spaces codepoint_s += spaces.length else codepoint = codepoint_str.to_i(16) if codepoint >= 0x110000 diagnostic :error, :unicode_point_too_large, nil, range(codepoint_s, codepoint_s + codepoint_str.length) break end @escape += codepoint.chr(Encoding::UTF_8) codepoint_s += codepoint_str.length end end end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 373 then # line 666 "lib/parser/lexer.rl" begin @escape = "" codepoints = tok(@escape_s + 2, p - 1) codepoint_s = @escape_s + 2 if @version < 24 if codepoints.start_with?(" ") || codepoints.start_with?("\t") diagnostic :fatal, :invalid_unicode_escape, nil, range(@escape_s + 2, @escape_s + 3) end if spaces_p = codepoints.index(/[ \t]{2}/) diagnostic :fatal, :invalid_unicode_escape, nil, range(codepoint_s + spaces_p + 1, codepoint_s + spaces_p + 2) end if codepoints.end_with?(" ") || codepoints.end_with?("\t") diagnostic :fatal, :invalid_unicode_escape, nil, range(p - 1, p) end end codepoints.scan(/([0-9a-fA-F]+)|([ \t]+)/).each do |(codepoint_str, spaces)| if spaces codepoint_s += spaces.length else codepoint = codepoint_str.to_i(16) if codepoint >= 0x110000 diagnostic :error, :unicode_point_too_large, nil, range(codepoint_s, codepoint_s + codepoint_str.length) break end @escape += codepoint.chr(Encoding::UTF_8) codepoint_s += codepoint_str.length end end end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 118 then # line 706 "lib/parser/lexer.rl" begin codepoint = @source_pts[p - 1] if @version >= 30 && (codepoint == 117 || codepoint == 85) # 'u' or 'U' diagnostic :fatal, :invalid_escape end if (@escape = ESCAPES[codepoint]).nil? @escape = encode_escape(@source_buffer.slice(p - 1)) end end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 146 then # line 706 "lib/parser/lexer.rl" begin codepoint = @source_pts[p - 1] if @version >= 30 && (codepoint == 117 || codepoint == 85) # 'u' or 'U' diagnostic :fatal, :invalid_escape end if (@escape = ESCAPES[codepoint]).nil? @escape = encode_escape(@source_buffer.slice(p - 1)) end end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 357 then # line 706 "lib/parser/lexer.rl" begin codepoint = @source_pts[p - 1] if @version >= 30 && (codepoint == 117 || codepoint == 85) # 'u' or 'U' diagnostic :fatal, :invalid_escape end if (@escape = ESCAPES[codepoint]).nil? @escape = encode_escape(@source_buffer.slice(p - 1)) end end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 121 then # line 718 "lib/parser/lexer.rl" begin diagnostic :fatal, :invalid_escape end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 149 then # line 718 "lib/parser/lexer.rl" begin diagnostic :fatal, :invalid_escape end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 360 then # line 718 "lib/parser/lexer.rl" begin diagnostic :fatal, :invalid_escape end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 123 then # line 745 "lib/parser/lexer.rl" begin @escape = "\x7f" end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 151 then # line 745 "lib/parser/lexer.rl" begin @escape = "\x7f" end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 362 then # line 745 "lib/parser/lexer.rl" begin @escape = "\x7f" end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 120 then # line 752 "lib/parser/lexer.rl" begin @escape = encode_escape(tok(@escape_s, p).to_i(8) % 0x100) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 148 then # line 752 "lib/parser/lexer.rl" begin @escape = encode_escape(tok(@escape_s, p).to_i(8) % 0x100) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 359 then # line 752 "lib/parser/lexer.rl" begin @escape = encode_escape(tok(@escape_s, p).to_i(8) % 0x100) end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 137 then # line 756 "lib/parser/lexer.rl" begin @escape = encode_escape(tok(@escape_s + 1, p).to_i(16)) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 165 then # line 756 "lib/parser/lexer.rl" begin @escape = encode_escape(tok(@escape_s + 1, p).to_i(16)) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 376 then # line 756 "lib/parser/lexer.rl" begin @escape = encode_escape(tok(@escape_s + 1, p).to_i(16)) end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 136 then # line 760 "lib/parser/lexer.rl" begin diagnostic :fatal, :invalid_hex_escape, nil, range(@escape_s - 1, p + 2) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 164 then # line 760 "lib/parser/lexer.rl" begin diagnostic :fatal, :invalid_hex_escape, nil, range(@escape_s - 1, p + 2) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 375 then # line 760 "lib/parser/lexer.rl" begin diagnostic :fatal, :invalid_hex_escape, nil, range(@escape_s - 1, p + 2) end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 131 then # line 766 "lib/parser/lexer.rl" begin @escape = tok(@escape_s + 1, p).to_i(16).chr(Encoding::UTF_8) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 159 then # line 766 "lib/parser/lexer.rl" begin @escape = tok(@escape_s + 1, p).to_i(16).chr(Encoding::UTF_8) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 370 then # line 766 "lib/parser/lexer.rl" begin @escape = tok(@escape_s + 1, p).to_i(16).chr(Encoding::UTF_8) end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 130 then # line 770 "lib/parser/lexer.rl" begin diagnostic :fatal, :invalid_unicode_escape, nil, range(@escape_s - 1, p) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 158 then # line 770 "lib/parser/lexer.rl" begin diagnostic :fatal, :invalid_unicode_escape, nil, range(@escape_s - 1, p) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 369 then # line 770 "lib/parser/lexer.rl" begin diagnostic :fatal, :invalid_unicode_escape, nil, range(@escape_s - 1, p) end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 135 then # line 776 "lib/parser/lexer.rl" begin diagnostic :fatal, :invalid_unicode_escape, nil, range(@escape_s - 1, p) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 163 then # line 776 "lib/parser/lexer.rl" begin diagnostic :fatal, :invalid_unicode_escape, nil, range(@escape_s - 1, p) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 374 then # line 776 "lib/parser/lexer.rl" begin diagnostic :fatal, :invalid_unicode_escape, nil, range(@escape_s - 1, p) end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 132 then # line 790 "lib/parser/lexer.rl" begin diagnostic :fatal, :unterminated_unicode, nil, range(p - 1, p) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 160 then # line 790 "lib/parser/lexer.rl" begin diagnostic :fatal, :unterminated_unicode, nil, range(p - 1, p) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 371 then # line 790 "lib/parser/lexer.rl" begin diagnostic :fatal, :unterminated_unicode, nil, range(p - 1, p) end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 119 then # line 816 "lib/parser/lexer.rl" begin diagnostic :fatal, :escape_eof, nil, range(p - 1, p) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 147 then # line 816 "lib/parser/lexer.rl" begin diagnostic :fatal, :escape_eof, nil, range(p - 1, p) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 358 then # line 816 "lib/parser/lexer.rl" begin diagnostic :fatal, :escape_eof, nil, range(p - 1, p) end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 171 then # line 822 "lib/parser/lexer.rl" begin @escape_s = p @escape = nil end # line 895 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 176 then # line 822 "lib/parser/lexer.rl" begin @escape_s = p @escape = nil end # line 895 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 57 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end when 30 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 1547 "lib/parser/lexer.rl" begin tm = p end when 32 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 1567 "lib/parser/lexer.rl" begin tm = p end when 34 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 1595 "lib/parser/lexer.rl" begin tm = p end when 213 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 1420 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 232 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 1438 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 240 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 1470 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 33 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 1607 "lib/parser/lexer.rl" begin @te = p+1 begin p = @ts - 1 begin @cs = 781 _goto_level = _again next end end end when 271 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 1612 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 263 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 1618 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = p - 1; begin @cs = 781 _goto_level = _again next end end end when 282 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 1696 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 294 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 1717 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 290 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 1720 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = p - 1; begin @cs = 781 _goto_level = _again next end end end when 58 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 1738 "lib/parser/lexer.rl" begin @te = p+1 begin emit(:tUNARY_NUM, tok(@ts, @ts + 1), @ts, @ts + 1) p = p - 1; @cs = 781; begin p += 1 _goto_level = _out next end end end when 49 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 2079 "lib/parser/lexer.rl" begin @te = p+1 begin emit(:tIDENTIFIER, ident_tok, ident_ts, ident_te) p = ident_te - 1 if !@static_env.nil? && @static_env.declared?(ident_tok) && @version < 25 @cs = 446; else @cs = 505; end begin p += 1 _goto_level = _out next end end end when 312 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 2095 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 393 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 2122 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 389 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 2125 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin if @in_kwarg p = p - 1; begin @cs = 781 _goto_level = _again next end else begin @cs = 185 _goto_level = _again next end end end end when 402 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 2153 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 399 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 2156 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin begin @cs = 185 _goto_level = _again next end end end when 486 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 2470 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 418 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 2473 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin begin @cs = 961 _goto_level = _again next end end end when 101 then # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 2544 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 262 then # line 1064 "lib/parser/lexer.rl" begin @cond.push(false); @cmdarg.push(false) current_literal = literal if current_literal current_literal.start_interp_brace end end # line 1514 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin if @lambda_stack.last == @paren_nest @lambda_stack.pop emit(:tLAMBEG, '{'.freeze, @te - 1, @te) else emit(:tLCURLY, '{'.freeze, @te - 1, @te) end @command_start = true @paren_nest += 1 @cs = 773; begin p += 1 _goto_level = _out next end end end when 284 then # line 1064 "lib/parser/lexer.rl" begin @cond.push(false); @cmdarg.push(false) current_literal = literal if current_literal current_literal.start_interp_brace end end # line 1680 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin if @lambda_stack.last == @paren_nest @lambda_stack.pop emit(:tLAMBEG, '{'.freeze) else emit(:tLBRACE_ARG, '{'.freeze) end @paren_nest += 1 @command_start = true @cs = 773; begin p += 1 _goto_level = _out next end end end when 384 then # line 1064 "lib/parser/lexer.rl" begin @cond.push(false); @cmdarg.push(false) current_literal = literal if current_literal current_literal.start_interp_brace end end # line 1960 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin if @lambda_stack.last == @paren_nest @lambda_stack.pop @command_start = true emit(:tLAMBEG, '{'.freeze) else emit(:tLBRACE, '{'.freeze) end @paren_nest += 1 begin p += 1 _goto_level = _out next end end end when 499 then # line 1064 "lib/parser/lexer.rl" begin @cond.push(false); @cmdarg.push(false) current_literal = literal if current_literal current_literal.start_interp_brace end end # line 2178 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin if @lambda_stack.last == @paren_nest @lambda_stack.pop if tok == '{'.freeze emit(:tLAMBEG, '{'.freeze) else # 'do' emit(:kDO_LAMBDA, 'do'.freeze) end else if tok == '{'.freeze emit(:tLCURLY, '{'.freeze) else # 'do' emit_do end end if tok == '{'.freeze @paren_nest += 1 end @command_start = true @cs = 773; begin p += 1 _goto_level = _out next end end end when 500 then # line 1073 "lib/parser/lexer.rl" begin current_literal = literal if current_literal if current_literal.end_interp_brace_and_try_closing if version?(18, 19) emit(:tRCURLY, '}'.freeze, p - 1, p) @cond.lexpop @cmdarg.lexpop else emit(:tSTRING_DEND, '}'.freeze, p - 1, p) end if current_literal.saved_herebody_s @herebody_s = current_literal.saved_herebody_s end p = p - 1; @cs = (next_state_for_literal(current_literal)); begin p += 1 _goto_level = _out next end end end @paren_nest -= 1 end # line 2415 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit_table(PUNCTUATION) if @version < 24 @cond.lexpop @cmdarg.lexpop else @cond.pop @cmdarg.pop end if tok == '}'.freeze || tok == ']'.freeze if @version >= 25 @cs = 781; else @cs = 511; end else # ) # fnext expr_endfn; ? end begin p += 1 _goto_level = _out next end end end when 60 then # line 1222 "lib/parser/lexer.rl" begin @sharp_s = p - 1 end # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end when 64 then # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end when 216 then # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 1420 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 231 then # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 1438 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 243 then # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 1470 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 265 then # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 1615 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin begin @cs = 781 _goto_level = _again next end end end when 280 then # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 1696 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 292 then # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 1717 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 318 then # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 2095 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 391 then # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 2122 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 401 then # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 2153 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 422 then # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 2470 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 103 then # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 2544 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 237 then # line 1266 "lib/parser/lexer.rl" begin tm = p end # line 1460 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tFID, tok(@ts, tm), @ts, tm) @cs = (arg_or_cmdarg(cmd_state)); p = tm - 1; begin p += 1 _goto_level = _out next end end end when 332 then # line 1266 "lib/parser/lexer.rl" begin tm = p end # line 1866 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tSYMBOL, tok(@ts + 1, tm), @ts, tm) p = tm - 1 @cs = 781; begin p += 1 _goto_level = _out next end end end when 303 then # line 1266 "lib/parser/lexer.rl" begin tm = p end # line 2068 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = @ts - 1 begin @cs = 781 _goto_level = _again next end end end when 415 then # line 1266 "lib/parser/lexer.rl" begin tm = p end # line 1 "NONE" begin case @act when 144 then begin begin p = (( @te))-1; end if @lambda_stack.last == @paren_nest @lambda_stack.pop if tok == '{'.freeze emit(:tLAMBEG, '{'.freeze) else # 'do' emit(:kDO_LAMBDA, 'do'.freeze) end else if tok == '{'.freeze emit(:tLCURLY, '{'.freeze) else # 'do' emit_do end end if tok == '{'.freeze @paren_nest += 1 end @command_start = true @cs = 773; begin p += 1 _goto_level = _out next end end when 145 then begin begin p = (( @te))-1; end emit_table(KEYWORDS) @cs = 333; begin p += 1 _goto_level = _out next end end when 146 then begin begin p = (( @te))-1; end emit(:kCLASS, 'class'.freeze, @ts, @ts + 5) emit(:tLSHFT, '<<'.freeze, @te - 2, @te) @cs = 773; begin p += 1 _goto_level = _out next end end when 147 then begin begin p = (( @te))-1; end emit_table(KEYWORDS) @cs = 543; begin p += 1 _goto_level = _out next end end when 148 then begin begin p = (( @te))-1; end emit_table(KEYWORDS) @command_start = true @cs = 773; begin p += 1 _goto_level = _out next end end when 149 then begin begin p = (( @te))-1; end emit_table(KEYWORDS) @cs = 519; begin p += 1 _goto_level = _out next end end when 150 then begin begin p = (( @te))-1; end emit_table(KEYWORDS) if version?(18) && tok == 'not'.freeze @cs = 543; begin p += 1 _goto_level = _out next end else @cs = 474; begin p += 1 _goto_level = _out next end end end when 151 then begin begin p = (( @te))-1; end if version?(18) emit(:tIDENTIFIER) unless !@static_env.nil? && @static_env.declared?(tok) @cs = (arg_or_cmdarg(cmd_state)); end else emit(:k__ENCODING__, '__ENCODING__'.freeze) end begin p += 1 _goto_level = _out next end end when 152 then begin begin p = (( @te))-1; end emit_table(KEYWORDS) begin p += 1 _goto_level = _out next end end when 153 then begin begin p = (( @te))-1; end digits = tok(@num_digits_s, @num_suffix_s) if digits.end_with? '_'.freeze diagnostic :error, :trailing_in_number, { :character => '_'.freeze }, range(@te - 1, @te) elsif digits.empty? && @num_base == 8 && version?(18) # 1.8 did not raise an error on 0o. digits = '0'.freeze elsif digits.empty? diagnostic :error, :empty_numeric elsif @num_base == 8 && (invalid_idx = digits.index(/[89]/)) invalid_s = @num_digits_s + invalid_idx diagnostic :error, :invalid_octal, nil, range(invalid_s, invalid_s + 1) end if version?(18, 19, 20) emit(:tINTEGER, digits.to_i(@num_base), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits.to_i(@num_base)) end begin p += 1 _goto_level = _out next end end when 155 then begin begin p = (( @te))-1; end if version?(18, 19, 20) diagnostic :error, :trailing_in_number, { :character => tok(@te - 1, @te) }, range(@te - 1, @te) else emit(:tINTEGER, tok(@ts, @te - 1).to_i, @ts, @te - 1) p = p - 1; begin p += 1 _goto_level = _out next end end end when 156 then begin begin p = (( @te))-1; end if version?(18, 19, 20) diagnostic :error, :trailing_in_number, { :character => tok(@te - 1, @te) }, range(@te - 1, @te) else emit(:tFLOAT, tok(@ts, @te - 1).to_f, @ts, @te - 1) p = p - 1; begin p += 1 _goto_level = _out next end end end when 157 then begin begin p = (( @te))-1; end digits = tok(@ts, @num_suffix_s) if version?(18, 19, 20) emit(:tFLOAT, Float(digits), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits) end begin p += 1 _goto_level = _out next end end when 159 then begin begin p = (( @te))-1; end emit(:tCONSTANT) @cs = (arg_or_cmdarg(cmd_state)); begin p += 1 _goto_level = _out next end end when 163 then begin begin p = (( @te))-1; end emit(:tIDENTIFIER) if !@static_env.nil? && @static_env.declared?(tok) @cs = 446; begin p += 1 _goto_level = _out next end else @cs = (arg_or_cmdarg(cmd_state)); begin p += 1 _goto_level = _out next end end end when 164 then begin begin p = (( @te))-1; end if tm == @te # Suffix was consumed, e.g. foo! emit(:tFID) else # Suffix was not consumed, e.g. foo!= emit(:tIDENTIFIER, tok(@ts, tm), @ts, tm) p = tm - 1 end @cs = 474; begin p += 1 _goto_level = _out next end end when 166 then begin begin p = (( @te))-1; end emit_table(PUNCTUATION); @cs = 773; begin p += 1 _goto_level = _out next end end when 167 then begin begin p = (( @te))-1; end emit_table(PUNCTUATION) @cs = 543; begin p += 1 _goto_level = _out next end end end end when 238 then # line 1267 "lib/parser/lexer.rl" begin tm = p - 2 end # line 1460 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tFID, tok(@ts, tm), @ts, tm) @cs = (arg_or_cmdarg(cmd_state)); p = tm - 1; begin p += 1 _goto_level = _out next end end end when 333 then # line 1267 "lib/parser/lexer.rl" begin tm = p - 2 end # line 1866 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tSYMBOL, tok(@ts + 1, tm), @ts, tm) p = tm - 1 @cs = 781; begin p += 1 _goto_level = _out next end end end when 305 then # line 1267 "lib/parser/lexer.rl" begin tm = p - 2 end # line 2068 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = @ts - 1 begin @cs = 781 _goto_level = _again next end end end when 416 then # line 1267 "lib/parser/lexer.rl" begin tm = p - 2 end # line 2379 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin if tm == @te # Suffix was consumed, e.g. foo! emit(:tFID) else # Suffix was not consumed, e.g. foo!= emit(:tIDENTIFIER, tok(@ts, tm), @ts, tm) p = tm - 1 end @cs = 474; begin p += 1 _goto_level = _out next end end end when 334 then # line 1272 "lib/parser/lexer.rl" begin tm = p end # line 1866 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tSYMBOL, tok(@ts + 1, tm), @ts, tm) p = tm - 1 @cs = 781; begin p += 1 _goto_level = _out next end end end when 306 then # line 1272 "lib/parser/lexer.rl" begin tm = p end # line 2068 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = @ts - 1 begin @cs = 781 _goto_level = _again next end end end when 335 then # line 1273 "lib/parser/lexer.rl" begin tm = p - 2 end # line 1866 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tSYMBOL, tok(@ts + 1, tm), @ts, tm) p = tm - 1 @cs = 781; begin p += 1 _goto_level = _out next end end end when 307 then # line 1273 "lib/parser/lexer.rl" begin tm = p - 2 end # line 2068 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = @ts - 1 begin @cs = 781 _goto_level = _again next end end end when 339 then # line 1274 "lib/parser/lexer.rl" begin tm = p - 2 end # line 1866 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tSYMBOL, tok(@ts + 1, tm), @ts, tm) p = tm - 1 @cs = 781; begin p += 1 _goto_level = _out next end end end when 310 then # line 1274 "lib/parser/lexer.rl" begin tm = p - 2 end # line 2068 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = @ts - 1 begin @cs = 781 _goto_level = _again next end end end when 338 then # line 1275 "lib/parser/lexer.rl" begin tm = p - 2 end # line 1866 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tSYMBOL, tok(@ts + 1, tm), @ts, tm) p = tm - 1 @cs = 781; begin p += 1 _goto_level = _out next end end end when 309 then # line 1275 "lib/parser/lexer.rl" begin tm = p - 2 end # line 1 "NONE" begin case @act when 98 then begin begin p = (( @te))-1; end emit(:tUNARY_NUM, tok(@ts, @ts + 1), @ts, @ts + 1) p = p - 1; @cs = 781; begin p += 1 _goto_level = _out next end end when 105 then begin begin p = (( @te))-1; end diagnostic :error, :unterminated_heredoc_id, nil, range(@ts, @ts + 1) end when 116 then begin begin p = (( @te))-1; end if @version >= 27 emit(:tPIPE, tok(@ts, @ts + 1), @ts, @ts + 1) p = p - 1; @cs = 543; begin p += 1 _goto_level = _out next end else p -= 2 begin @cs = 781 _goto_level = _again next end end end when 120 then begin begin p = (( @te))-1; end emit_table(PUNCTUATION_BEGIN) begin p += 1 _goto_level = _out next end end when 121 then begin begin p = (( @te))-1; end emit(:kRESCUE, 'rescue'.freeze, @ts, tm) p = tm - 1 @cs = 519; begin p += 1 _goto_level = _out next end end when 122 then begin begin p = (( @te))-1; end emit_table(KEYWORDS_BEGIN) @command_start = true @cs = 773; begin p += 1 _goto_level = _out next end end when 126 then begin begin p = (( @te))-1; end p = @ts - 1 begin @cs = 781 _goto_level = _again next end end when 127 then begin begin p = (( @te))-1; end emit(:tIDENTIFIER) if !@static_env.nil? && @static_env.declared?(tok) @cs = 446; begin p += 1 _goto_level = _out next end else @cs = (arg_or_cmdarg(cmd_state)); begin p += 1 _goto_level = _out next end end end when 131 then begin begin p = (( @te))-1; end p = @ts - 1; begin @cs = 781 _goto_level = _again next end end end end when 336 then # line 1276 "lib/parser/lexer.rl" begin tm = p - 3 end # line 1866 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tSYMBOL, tok(@ts + 1, tm), @ts, tm) p = tm - 1 @cs = 781; begin p += 1 _goto_level = _out next end end end when 308 then # line 1276 "lib/parser/lexer.rl" begin tm = p - 3 end # line 2068 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin p = @ts - 1 begin @cs = 781 _goto_level = _again next end end end when 337 then # line 1281 "lib/parser/lexer.rl" begin tm = p - 2 end # line 1866 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tSYMBOL, tok(@ts + 1, tm), @ts, tm) p = tm - 1 @cs = 781; begin p += 1 _goto_level = _out next end end end when 481 then # line 1286 "lib/parser/lexer.rl" begin tm = p - 2 end # line 2361 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tCONSTANT, tok(@ts, tm), @ts, tm) p = tm - 1; begin p += 1 _goto_level = _out next end end end when 261 then # line 1292 "lib/parser/lexer.rl" begin @cond.push(false); @cmdarg.push(false) @paren_nest += 1 end # line 1508 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tLBRACK, '['.freeze, @te - 1, @te) @cs = 543; begin p += 1 _goto_level = _out next end end end when 377 then # line 1292 "lib/parser/lexer.rl" begin @cond.push(false); @cmdarg.push(false) @paren_nest += 1 end # line 1974 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tLBRACK, '['.freeze) begin p += 1 _goto_level = _out next end end end when 484 then # line 1292 "lib/parser/lexer.rl" begin @cond.push(false); @cmdarg.push(false) @paren_nest += 1 end # line 2448 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tLBRACK2, '['.freeze) @cs = 543; begin p += 1 _goto_level = _out next end end end when 487 then # line 1298 "lib/parser/lexer.rl" begin @paren_nest -= 1 end # line 2415 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit_table(PUNCTUATION) if @version < 24 @cond.lexpop @cmdarg.lexpop else @cond.pop @cmdarg.pop end if tok == '}'.freeze || tok == ']'.freeze if @version >= 25 @cs = 781; else @cs = 511; end else # ) # fnext expr_endfn; ? end begin p += 1 _goto_level = _out next end end end when 253 then # line 1305 "lib/parser/lexer.rl" begin @cond.push(false); @cmdarg.push(false) @paren_nest += 1 if version?(18) @command_start = true end end # line 1489 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin if version?(18) emit(:tLPAREN2, '('.freeze, @te - 1, @te) @cs = 773; begin p += 1 _goto_level = _out next end else emit(:tLPAREN_ARG, '('.freeze, @te - 1, @te) @cs = 543; begin p += 1 _goto_level = _out next end end end end when 266 then # line 1305 "lib/parser/lexer.rl" begin @cond.push(false); @cmdarg.push(false) @paren_nest += 1 if version?(18) @command_start = true end end # line 1502 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tLPAREN2, '('.freeze) @cs = 543; begin p += 1 _goto_level = _out next end end end when 274 then # line 1305 "lib/parser/lexer.rl" begin @cond.push(false); @cmdarg.push(false) @paren_nest += 1 if version?(18) @command_start = true end end # line 1634 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tLPAREN_ARG, '('.freeze, @te - 1, @te) if version?(18) @cs = 773; begin p += 1 _goto_level = _out next end else @cs = 543; begin p += 1 _goto_level = _out next end end end end when 323 then # line 1305 "lib/parser/lexer.rl" begin @cond.push(false); @cmdarg.push(false) @paren_nest += 1 if version?(18) @command_start = true end end # line 1979 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:tLPAREN, '('.freeze) begin p += 1 _goto_level = _out next end end end when 428 then # line 1305 "lib/parser/lexer.rl" begin @cond.push(false); @cmdarg.push(false) @paren_nest += 1 if version?(18) @command_start = true end end # line 2411 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit_table(PUNCTUATION) @cs = 543; begin p += 1 _goto_level = _out next end end end when 429 then # line 1315 "lib/parser/lexer.rl" begin @paren_nest -= 1 end # line 2415 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit_table(PUNCTUATION) if @version < 24 @cond.lexpop @cmdarg.lexpop else @cond.pop @cmdarg.pop end if tok == '}'.freeze || tok == ']'.freeze if @version >= 25 @cs = 781; else @cs = 511; end else # ) # fnext expr_endfn; ? end begin p += 1 _goto_level = _out next end end end when 71 then # line 1787 "lib/parser/lexer.rl" begin heredoc_e = p end # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end when 347 then # line 1788 "lib/parser/lexer.rl" begin new_herebody_s = p end # line 1789 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin tok(@ts, heredoc_e) =~ /^<<(-?)(~?)(["'`]?)(.*)\3$/m indent = !$1.empty? || !$2.empty? dedent_body = !$2.empty? type = $3.empty? ? '<<"'.freeze : ('<<'.freeze + $3) delimiter = $4 if @version >= 27 if delimiter.count("\n") > 0 || delimiter.count("\r") > 0 diagnostic :error, :unterminated_heredoc_id, nil, range(@ts, @ts + 1) end elsif @version >= 24 if delimiter.count("\n") > 0 if delimiter.end_with?("\n") diagnostic :warning, :heredoc_id_ends_with_nl, nil, range(@ts, @ts + 1) delimiter = delimiter.rstrip else diagnostic :fatal, :heredoc_id_has_newline, nil, range(@ts, @ts + 1) end end end if dedent_body && version?(18, 19, 20, 21, 22) emit(:tLSHFT, '<<'.freeze, @ts, @ts + 2) p = @ts + 1 @cs = 543; begin p += 1 _goto_level = _out next end else @cs = (push_literal(type, delimiter, @ts, heredoc_e, indent, dedent_body)); @herebody_s ||= new_herebody_s p = @herebody_s - 1 end end end when 342 then # line 1879 "lib/parser/lexer.rl" begin tm = p - 1; diag_msg = :ivar_name end # line 1882 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin if @version >= 27 diagnostic :error, diag_msg, { name: tok(tm, @te) }, range(tm, @te) else emit(:tCOLON, tok(@ts, @ts + 1), @ts, @ts + 1) p = @ts end @cs = 781; begin p += 1 _goto_level = _out next end end end when 345 then # line 1880 "lib/parser/lexer.rl" begin tm = p - 2; diag_msg = :cvar_name end # line 1882 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin if @version >= 27 diagnostic :error, diag_msg, { name: tok(tm, @te) }, range(tm, @te) else emit(:tCOLON, tok(@ts, @ts + 1), @ts, @ts + 1) p = @ts end @cs = 781; begin p += 1 _goto_level = _out next end end end when 353 then # line 1900 "lib/parser/lexer.rl" begin @escape = nil end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 380 then # line 1989 "lib/parser/lexer.rl" begin tm = p end # line 1990 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin emit(:kRESCUE, 'rescue'.freeze, @ts, tm) p = tm - 1 @cs = 519; begin p += 1 _goto_level = _out next end end end when 471 then # line 2263 "lib/parser/lexer.rl" begin @num_base = 16; @num_digits_s = p end # line 2269 "lib/parser/lexer.rl" begin @num_suffix_s = p end when 465 then # line 2264 "lib/parser/lexer.rl" begin @num_base = 10; @num_digits_s = p end # line 2269 "lib/parser/lexer.rl" begin @num_suffix_s = p end when 468 then # line 2265 "lib/parser/lexer.rl" begin @num_base = 8; @num_digits_s = p end # line 2269 "lib/parser/lexer.rl" begin @num_suffix_s = p end when 462 then # line 2266 "lib/parser/lexer.rl" begin @num_base = 2; @num_digits_s = p end # line 2269 "lib/parser/lexer.rl" begin @num_suffix_s = p end when 477 then # line 2267 "lib/parser/lexer.rl" begin @num_base = 10; @num_digits_s = @ts end # line 2269 "lib/parser/lexer.rl" begin @num_suffix_s = p end when 440 then # line 2268 "lib/parser/lexer.rl" begin @num_base = 8; @num_digits_s = @ts end # line 2269 "lib/parser/lexer.rl" begin @num_suffix_s = p end when 478 then # line 2269 "lib/parser/lexer.rl" begin @num_suffix_s = p end # line 634 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tINTEGER, chars) } end when 89 then # line 2515 "lib/parser/lexer.rl" begin tm = p end # line 2516 "lib/parser/lexer.rl" begin @te = p+1 begin p = tm - 1; begin @cs = 781 _goto_level = _again next end end end when 8 then # line 1 "NONE" begin @te = p+1 end # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end when 444 then # line 1 "NONE" begin @te = p+1 end # line 2327 "lib/parser/lexer.rl" begin @num_suffix_s = p end when 222 then # line 1 "NONE" begin @te = p+1 end # line 1379 "lib/parser/lexer.rl" begin @act = 43; end when 209 then # line 1 "NONE" begin @te = p+1 end # line 1383 "lib/parser/lexer.rl" begin @act = 44; end when 205 then # line 1 "NONE" begin @te = p+1 end # line 1387 "lib/parser/lexer.rl" begin @act = 45; end when 26 then # line 1 "NONE" begin @te = p+1 end # line 1551 "lib/parser/lexer.rl" begin @act = 71; end when 255 then # line 1 "NONE" begin @te = p+1 end # line 1568 "lib/parser/lexer.rl" begin @act = 72; end when 27 then # line 1 "NONE" begin @te = p+1 end # line 1607 "lib/parser/lexer.rl" begin @act = 77; end when 248 then # line 1 "NONE" begin @te = p+1 end # line 1612 "lib/parser/lexer.rl" begin @act = 78; end when 275 then # line 1 "NONE" begin @te = p+1 end # line 1644 "lib/parser/lexer.rl" begin @act = 84; end when 45 then # line 1 "NONE" begin @te = p+1 end # line 1657 "lib/parser/lexer.rl" begin @act = 85; end when 296 then # line 1 "NONE" begin @te = p+1 end # line 1711 "lib/parser/lexer.rl" begin @act = 92; end when 285 then # line 1 "NONE" begin @te = p+1 end # line 1715 "lib/parser/lexer.rl" begin @act = 93; end when 69 then # line 1 "NONE" begin @te = p+1 end # line 1835 "lib/parser/lexer.rl" begin @act = 105; end when 385 then # line 1 "NONE" begin @te = p+1 end # line 1943 "lib/parser/lexer.rl" begin @act = 116; end when 299 then # line 1 "NONE" begin @te = p+1 end # line 1984 "lib/parser/lexer.rl" begin @act = 120; end when 379 then # line 1 "NONE" begin @te = p+1 end # line 1990 "lib/parser/lexer.rl" begin @act = 121; end when 378 then # line 1 "NONE" begin @te = p+1 end # line 1996 "lib/parser/lexer.rl" begin @act = 122; end when 74 then # line 1 "NONE" begin @te = p+1 end # line 2068 "lib/parser/lexer.rl" begin @act = 126; end when 297 then # line 1 "NONE" begin @te = p+1 end # line 1320 "lib/parser/lexer.rl" begin @act = 127; end when 300 then # line 1 "NONE" begin @te = p+1 end # line 2114 "lib/parser/lexer.rl" begin @act = 131; end when 495 then # line 1 "NONE" begin @te = p+1 end # line 2178 "lib/parser/lexer.rl" begin @act = 144; end when 490 then # line 1 "NONE" begin @te = p+1 end # line 2207 "lib/parser/lexer.rl" begin @act = 145; end when 498 then # line 1 "NONE" begin @te = p+1 end # line 2217 "lib/parser/lexer.rl" begin @act = 147; end when 491 then # line 1 "NONE" begin @te = p+1 end # line 2222 "lib/parser/lexer.rl" begin @act = 148; end when 492 then # line 1 "NONE" begin @te = p+1 end # line 2227 "lib/parser/lexer.rl" begin @act = 149; end when 497 then # line 1 "NONE" begin @te = p+1 end # line 2231 "lib/parser/lexer.rl" begin @act = 150; end when 489 then # line 1 "NONE" begin @te = p+1 end # line 2242 "lib/parser/lexer.rl" begin @act = 151; end when 483 then # line 1 "NONE" begin @te = p+1 end # line 2256 "lib/parser/lexer.rl" begin @act = 152; end when 409 then # line 1 "NONE" begin @te = p+1 end # line 2270 "lib/parser/lexer.rl" begin @act = 153; end when 442 then # line 1 "NONE" begin @te = p+1 end # line 2314 "lib/parser/lexer.rl" begin @act = 156; end when 81 then # line 1 "NONE" begin @te = p+1 end # line 2329 "lib/parser/lexer.rl" begin @act = 157; end when 412 then # line 1 "NONE" begin @te = p+1 end # line 2357 "lib/parser/lexer.rl" begin @act = 159; end when 403 then # line 1 "NONE" begin @te = p+1 end # line 1320 "lib/parser/lexer.rl" begin @act = 163; end when 414 then # line 1 "NONE" begin @te = p+1 end # line 2379 "lib/parser/lexer.rl" begin @act = 164; end when 407 then # line 1 "NONE" begin @te = p+1 end # line 2405 "lib/parser/lexer.rl" begin @act = 166; end when 413 then # line 1 "NONE" begin @te = p+1 end # line 2411 "lib/parser/lexer.rl" begin @act = 167; end when 87 then # line 1 "NONE" begin @te = p+1 end # line 2502 "lib/parser/lexer.rl" begin @act = 180; end when 502 then # line 1 "NONE" begin @te = p+1 end # line 2519 "lib/parser/lexer.rl" begin @act = 182; end when 177 then # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end # line 950 "lib/parser/lexer.rl" begin @te = p+1 begin current_literal = literal if @te == pe diagnostic :fatal, :string_eof, nil, range(current_literal.str_s, current_literal.str_s + 1) end if current_literal.heredoc? line = tok(@herebody_s, @ts).gsub(/\r+$/, ''.freeze) if version?(18, 19, 20) # See ruby:c48b4209c line = line.gsub(/\r.*$/, ''.freeze) end # Try ending the heredoc with the complete most recently # scanned line. @herebody_s always refers to the start of such line. if current_literal.nest_and_try_closing(line, @herebody_s, @ts) # Adjust @herebody_s to point to the next line. @herebody_s = @te # Continue regular lexing after the heredoc reference (<<END). p = current_literal.heredoc_e - 1 @cs = (pop_literal); begin p += 1 _goto_level = _out next end else # Calculate indentation level for <<~HEREDOCs. current_literal.infer_indent_level(line) # Ditto. @herebody_s = @te end else # Try ending the literal with a newline. if current_literal.nest_and_try_closing(tok, @ts, @te) @cs = (pop_literal); begin p += 1 _goto_level = _out next end end if @herebody_s # This is a regular literal intertwined with a heredoc. Like: # # p <<-foo+"1 # bar # foo # 2" # # which, incidentally, evaluates to "bar\n1\n2". p = @herebody_s - 1 @herebody_s = nil end end if current_literal.words? && !eof_codepoint?(@source_pts[p]) current_literal.extend_space @ts, @te else # A literal newline is appended if the heredoc was _not_ closed # this time (see fbreak above). See also Literal#nest_and_try_closing # for rationale of calling #flush_string here. current_literal.extend_string tok, @ts, @te current_literal.flush_string end end end # line 822 "lib/parser/lexer.rl" begin @escape_s = p @escape = nil end when 124 then # line 706 "lib/parser/lexer.rl" begin codepoint = @source_pts[p - 1] if @version >= 30 && (codepoint == 117 || codepoint == 85) # 'u' or 'U' diagnostic :fatal, :invalid_escape end if (@escape = ESCAPES[codepoint]).nil? @escape = encode_escape(@source_buffer.slice(p - 1)) end end # line 730 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord & 0x9f) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 152 then # line 706 "lib/parser/lexer.rl" begin codepoint = @source_pts[p - 1] if @version >= 30 && (codepoint == 117 || codepoint == 85) # 'u' or 'U' diagnostic :fatal, :invalid_escape end if (@escape = ESCAPES[codepoint]).nil? @escape = encode_escape(@source_buffer.slice(p - 1)) end end # line 730 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord & 0x9f) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 363 then # line 706 "lib/parser/lexer.rl" begin codepoint = @source_pts[p - 1] if @version >= 30 && (codepoint == 117 || codepoint == 85) # 'u' or 'U' diagnostic :fatal, :invalid_escape end if (@escape = ESCAPES[codepoint]).nil? @escape = encode_escape(@source_buffer.slice(p - 1)) end end # line 730 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord & 0x9f) end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 129 then # line 706 "lib/parser/lexer.rl" begin codepoint = @source_pts[p - 1] if @version >= 30 && (codepoint == 117 || codepoint == 85) # 'u' or 'U' diagnostic :fatal, :invalid_escape end if (@escape = ESCAPES[codepoint]).nil? @escape = encode_escape(@source_buffer.slice(p - 1)) end end # line 734 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord | 0x80) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 157 then # line 706 "lib/parser/lexer.rl" begin codepoint = @source_pts[p - 1] if @version >= 30 && (codepoint == 117 || codepoint == 85) # 'u' or 'U' diagnostic :fatal, :invalid_escape end if (@escape = ESCAPES[codepoint]).nil? @escape = encode_escape(@source_buffer.slice(p - 1)) end end # line 734 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord | 0x80) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 368 then # line 706 "lib/parser/lexer.rl" begin codepoint = @source_pts[p - 1] if @version >= 30 && (codepoint == 117 || codepoint == 85) # 'u' or 'U' diagnostic :fatal, :invalid_escape end if (@escape = ESCAPES[codepoint]).nil? @escape = encode_escape(@source_buffer.slice(p - 1)) end end # line 734 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord | 0x80) end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 122 then # line 722 "lib/parser/lexer.rl" begin @escape = @source_buffer.slice(p - 1).chr if @version >= 27 && ((0..8).include?(@escape.ord) || (14..31).include?(@escape.ord)) diagnostic :fatal, :invalid_escape end end # line 730 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord & 0x9f) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 150 then # line 722 "lib/parser/lexer.rl" begin @escape = @source_buffer.slice(p - 1).chr if @version >= 27 && ((0..8).include?(@escape.ord) || (14..31).include?(@escape.ord)) diagnostic :fatal, :invalid_escape end end # line 730 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord & 0x9f) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 361 then # line 722 "lib/parser/lexer.rl" begin @escape = @source_buffer.slice(p - 1).chr if @version >= 27 && ((0..8).include?(@escape.ord) || (14..31).include?(@escape.ord)) diagnostic :fatal, :invalid_escape end end # line 730 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord & 0x9f) end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 128 then # line 722 "lib/parser/lexer.rl" begin @escape = @source_buffer.slice(p - 1).chr if @version >= 27 && ((0..8).include?(@escape.ord) || (14..31).include?(@escape.ord)) diagnostic :fatal, :invalid_escape end end # line 734 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord | 0x80) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 156 then # line 722 "lib/parser/lexer.rl" begin @escape = @source_buffer.slice(p - 1).chr if @version >= 27 && ((0..8).include?(@escape.ord) || (14..31).include?(@escape.ord)) diagnostic :fatal, :invalid_escape end end # line 734 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord | 0x80) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 367 then # line 722 "lib/parser/lexer.rl" begin @escape = @source_buffer.slice(p - 1).chr if @version >= 27 && ((0..8).include?(@escape.ord) || (14..31).include?(@escape.ord)) diagnostic :fatal, :invalid_escape end end # line 734 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord | 0x80) end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 126 then # line 745 "lib/parser/lexer.rl" begin @escape = "\x7f" end # line 734 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord | 0x80) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 154 then # line 745 "lib/parser/lexer.rl" begin @escape = "\x7f" end # line 734 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord | 0x80) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 365 then # line 745 "lib/parser/lexer.rl" begin @escape = "\x7f" end # line 734 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord | 0x80) end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 133 then # line 776 "lib/parser/lexer.rl" begin diagnostic :fatal, :invalid_unicode_escape, nil, range(@escape_s - 1, p) end # line 790 "lib/parser/lexer.rl" begin diagnostic :fatal, :unterminated_unicode, nil, range(p - 1, p) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 161 then # line 776 "lib/parser/lexer.rl" begin diagnostic :fatal, :invalid_unicode_escape, nil, range(@escape_s - 1, p) end # line 790 "lib/parser/lexer.rl" begin diagnostic :fatal, :unterminated_unicode, nil, range(p - 1, p) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 372 then # line 776 "lib/parser/lexer.rl" begin diagnostic :fatal, :invalid_unicode_escape, nil, range(@escape_s - 1, p) end # line 790 "lib/parser/lexer.rl" begin diagnostic :fatal, :unterminated_unicode, nil, range(p - 1, p) end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 116 then # line 822 "lib/parser/lexer.rl" begin @escape_s = p @escape = nil end # line 816 "lib/parser/lexer.rl" begin diagnostic :fatal, :escape_eof, nil, range(p - 1, p) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 145 then # line 822 "lib/parser/lexer.rl" begin @escape_s = p @escape = nil end # line 816 "lib/parser/lexer.rl" begin diagnostic :fatal, :escape_eof, nil, range(p - 1, p) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 356 then # line 822 "lib/parser/lexer.rl" begin @escape_s = p @escape = nil end # line 816 "lib/parser/lexer.rl" begin diagnostic :fatal, :escape_eof, nil, range(p - 1, p) end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 61 then # line 1222 "lib/parser/lexer.rl" begin @sharp_s = p - 1 end # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end when 215 then # line 1222 "lib/parser/lexer.rl" begin @sharp_s = p - 1 end # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 1420 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 230 then # line 1222 "lib/parser/lexer.rl" begin @sharp_s = p - 1 end # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 1438 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 242 then # line 1222 "lib/parser/lexer.rl" begin @sharp_s = p - 1 end # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 1470 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 264 then # line 1222 "lib/parser/lexer.rl" begin @sharp_s = p - 1 end # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 1615 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin begin @cs = 781 _goto_level = _again next end end end when 279 then # line 1222 "lib/parser/lexer.rl" begin @sharp_s = p - 1 end # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 1696 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 291 then # line 1222 "lib/parser/lexer.rl" begin @sharp_s = p - 1 end # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 1717 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 317 then # line 1222 "lib/parser/lexer.rl" begin @sharp_s = p - 1 end # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 2095 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 390 then # line 1222 "lib/parser/lexer.rl" begin @sharp_s = p - 1 end # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 2122 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 400 then # line 1222 "lib/parser/lexer.rl" begin @sharp_s = p - 1 end # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 2153 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 421 then # line 1222 "lib/parser/lexer.rl" begin @sharp_s = p - 1 end # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 2470 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 102 then # line 1222 "lib/parser/lexer.rl" begin @sharp_s = p - 1 end # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 2544 "lib/parser/lexer.rl" begin @te = p p = p - 1; end when 473 then # line 2267 "lib/parser/lexer.rl" begin @num_base = 10; @num_digits_s = @ts end # line 2269 "lib/parser/lexer.rl" begin @num_suffix_s = p end # line 634 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tINTEGER, chars) } end when 437 then # line 2268 "lib/parser/lexer.rl" begin @num_base = 8; @num_digits_s = @ts end # line 2269 "lib/parser/lexer.rl" begin @num_suffix_s = p end # line 634 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tINTEGER, chars) } end when 452 then # line 2269 "lib/parser/lexer.rl" begin @num_suffix_s = p end # line 634 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tINTEGER, chars) } end # line 2270 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin digits = tok(@num_digits_s, @num_suffix_s) if digits.end_with? '_'.freeze diagnostic :error, :trailing_in_number, { :character => '_'.freeze }, range(@te - 1, @te) elsif digits.empty? && @num_base == 8 && version?(18) # 1.8 did not raise an error on 0o. digits = '0'.freeze elsif digits.empty? diagnostic :error, :empty_numeric elsif @num_base == 8 && (invalid_idx = digits.index(/[89]/)) invalid_s = @num_digits_s + invalid_idx diagnostic :error, :invalid_octal, nil, range(invalid_s, invalid_s + 1) end if version?(18, 19, 20) emit(:tINTEGER, digits.to_i(@num_base), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits.to_i(@num_base)) end begin p += 1 _goto_level = _out next end end end when 445 then # line 2326 "lib/parser/lexer.rl" begin @num_suffix_s = p end # line 643 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tFLOAT, Float(chars)) } end # line 2329 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin digits = tok(@ts, @num_suffix_s) if version?(18, 19, 20) emit(:tFLOAT, Float(digits), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits) end begin p += 1 _goto_level = _out next end end end when 441 then # line 2327 "lib/parser/lexer.rl" begin @num_suffix_s = p end # line 643 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tFLOAT, Float(chars)) } end # line 2329 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin digits = tok(@ts, @num_suffix_s) if version?(18, 19, 20) emit(:tFLOAT, Float(digits), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits) end begin p += 1 _goto_level = _out next end end end when 270 then # line 1 "NONE" begin @te = p+1 end # line 501 "lib/parser/lexer.rl" begin # Record position of a newline for precise location reporting on tNL # tokens. # # This action is embedded directly into c_nl, as it is idempotent and # there are no cases when we need to skip it. @newline_s = p end # line 1612 "lib/parser/lexer.rl" begin @act = 78; end when 35 then # line 1 "NONE" begin @te = p+1 end # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 1607 "lib/parser/lexer.rl" begin @act = 77; end when 46 then # line 1 "NONE" begin @te = p+1 end # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 1657 "lib/parser/lexer.rl" begin @act = 85; end when 94 then # line 1 "NONE" begin @te = p+1 end # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 2502 "lib/parser/lexer.rl" begin @act = 180; end when 65 then # line 1 "NONE" begin @te = p+1 end # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 1738 "lib/parser/lexer.rl" begin @act = 98; end when 84 then # line 1 "NONE" begin @te = p+1 end # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 2211 "lib/parser/lexer.rl" begin @act = 146; end when 93 then # line 1 "NONE" begin @te = p+1 end # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 2502 "lib/parser/lexer.rl" begin @act = 180; end when 37 then # line 1 "NONE" begin @te = p+1 end # line 1567 "lib/parser/lexer.rl" begin tm = p end # line 1568 "lib/parser/lexer.rl" begin @act = 72; end when 382 then # line 1 "NONE" begin @te = p+1 end # line 1989 "lib/parser/lexer.rl" begin tm = p end # line 2068 "lib/parser/lexer.rl" begin @act = 126; end when 381 then # line 1 "NONE" begin @te = p+1 end # line 1989 "lib/parser/lexer.rl" begin tm = p end # line 1320 "lib/parser/lexer.rl" begin @act = 127; end when 474 then # line 1 "NONE" begin @te = p+1 end # line 2267 "lib/parser/lexer.rl" begin @num_base = 10; @num_digits_s = @ts end # line 2270 "lib/parser/lexer.rl" begin @act = 153; end when 127 then # line 706 "lib/parser/lexer.rl" begin codepoint = @source_pts[p - 1] if @version >= 30 && (codepoint == 117 || codepoint == 85) # 'u' or 'U' diagnostic :fatal, :invalid_escape end if (@escape = ESCAPES[codepoint]).nil? @escape = encode_escape(@source_buffer.slice(p - 1)) end end # line 730 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord & 0x9f) end # line 734 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord | 0x80) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 155 then # line 706 "lib/parser/lexer.rl" begin codepoint = @source_pts[p - 1] if @version >= 30 && (codepoint == 117 || codepoint == 85) # 'u' or 'U' diagnostic :fatal, :invalid_escape end if (@escape = ESCAPES[codepoint]).nil? @escape = encode_escape(@source_buffer.slice(p - 1)) end end # line 730 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord & 0x9f) end # line 734 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord | 0x80) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 366 then # line 706 "lib/parser/lexer.rl" begin codepoint = @source_pts[p - 1] if @version >= 30 && (codepoint == 117 || codepoint == 85) # 'u' or 'U' diagnostic :fatal, :invalid_escape end if (@escape = ESCAPES[codepoint]).nil? @escape = encode_escape(@source_buffer.slice(p - 1)) end end # line 730 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord & 0x9f) end # line 734 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord | 0x80) end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 125 then # line 722 "lib/parser/lexer.rl" begin @escape = @source_buffer.slice(p - 1).chr if @version >= 27 && ((0..8).include?(@escape.ord) || (14..31).include?(@escape.ord)) diagnostic :fatal, :invalid_escape end end # line 730 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord & 0x9f) end # line 734 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord | 0x80) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 153 then # line 722 "lib/parser/lexer.rl" begin @escape = @source_buffer.slice(p - 1).chr if @version >= 27 && ((0..8).include?(@escape.ord) || (14..31).include?(@escape.ord)) diagnostic :fatal, :invalid_escape end end # line 730 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord & 0x9f) end # line 734 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord | 0x80) end # line 895 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin current_literal = literal # Get the first character after the backslash. escaped_char = @source_buffer.slice(@escape_s).chr if current_literal.munge_escape? escaped_char # If this particular literal uses this character as an opening # or closing delimiter, it is an escape sequence for that # particular character. Write it without the backslash. if current_literal.regexp? && REGEXP_META_CHARACTERS.match(escaped_char) # Regular expressions should include escaped delimiters in their # escaped form, except when the escaped character is # a closing delimiter but not a regexp metacharacter. # # The backslash itself cannot be used as a closing delimiter # at the same time as an escape symbol, but it is always munged, # so this branch also executes for the non-closing-delimiter case # for the backslash. current_literal.extend_string(tok, @ts, @te) else current_literal.extend_string(escaped_char, @ts, @te) end else # It does not. So this is an actual escape sequence, yay! if current_literal.squiggly_heredoc? && escaped_char == "\n".freeze # Squiggly heredocs like # <<~-HERE # 1\ # 2 # HERE # treat '\' as a line continuation, but still dedent the body, so the heredoc above becomes "12\n". # This information is emitted as is, without escaping, # later this escape sequence (\\\n) gets handled manually in the Lexer::Dedenter current_literal.extend_string(tok, @ts, @te) elsif current_literal.supports_line_continuation_via_slash? && escaped_char == "\n".freeze # Heredocs, regexp and a few other types of literals support line # continuation via \\\n sequence. The code like # "a\ # b" # must be parsed as "ab" current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) elsif current_literal.regexp? # Regular expressions should include escape sequences in their # escaped form. On the other hand, escaped newlines are removed (in cases like "\\C-\\\n\\M-x") current_literal.extend_string(tok.gsub("\\\n".freeze, ''.freeze), @ts, @te) else current_literal.extend_string(@escape || tok, @ts, @te) end end end end when 364 then # line 722 "lib/parser/lexer.rl" begin @escape = @source_buffer.slice(p - 1).chr if @version >= 27 && ((0..8).include?(@escape.ord) || (14..31).include?(@escape.ord)) diagnostic :fatal, :invalid_escape end end # line 730 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord & 0x9f) end # line 734 "lib/parser/lexer.rl" begin @escape = encode_escape(@escape[0].ord | 0x80) end # line 1902 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin value = @escape || tok(@ts + 1) if version?(18) emit(:tINTEGER, value.getbyte(0)) else emit(:tCHARACTER, value) end @cs = 781; begin p += 1 _goto_level = _out next end end end when 469 then # line 2263 "lib/parser/lexer.rl" begin @num_base = 16; @num_digits_s = p end # line 2269 "lib/parser/lexer.rl" begin @num_suffix_s = p end # line 634 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tINTEGER, chars) } end # line 2270 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin digits = tok(@num_digits_s, @num_suffix_s) if digits.end_with? '_'.freeze diagnostic :error, :trailing_in_number, { :character => '_'.freeze }, range(@te - 1, @te) elsif digits.empty? && @num_base == 8 && version?(18) # 1.8 did not raise an error on 0o. digits = '0'.freeze elsif digits.empty? diagnostic :error, :empty_numeric elsif @num_base == 8 && (invalid_idx = digits.index(/[89]/)) invalid_s = @num_digits_s + invalid_idx diagnostic :error, :invalid_octal, nil, range(invalid_s, invalid_s + 1) end if version?(18, 19, 20) emit(:tINTEGER, digits.to_i(@num_base), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits.to_i(@num_base)) end begin p += 1 _goto_level = _out next end end end when 463 then # line 2264 "lib/parser/lexer.rl" begin @num_base = 10; @num_digits_s = p end # line 2269 "lib/parser/lexer.rl" begin @num_suffix_s = p end # line 634 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tINTEGER, chars) } end # line 2270 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin digits = tok(@num_digits_s, @num_suffix_s) if digits.end_with? '_'.freeze diagnostic :error, :trailing_in_number, { :character => '_'.freeze }, range(@te - 1, @te) elsif digits.empty? && @num_base == 8 && version?(18) # 1.8 did not raise an error on 0o. digits = '0'.freeze elsif digits.empty? diagnostic :error, :empty_numeric elsif @num_base == 8 && (invalid_idx = digits.index(/[89]/)) invalid_s = @num_digits_s + invalid_idx diagnostic :error, :invalid_octal, nil, range(invalid_s, invalid_s + 1) end if version?(18, 19, 20) emit(:tINTEGER, digits.to_i(@num_base), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits.to_i(@num_base)) end begin p += 1 _goto_level = _out next end end end when 466 then # line 2265 "lib/parser/lexer.rl" begin @num_base = 8; @num_digits_s = p end # line 2269 "lib/parser/lexer.rl" begin @num_suffix_s = p end # line 634 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tINTEGER, chars) } end # line 2270 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin digits = tok(@num_digits_s, @num_suffix_s) if digits.end_with? '_'.freeze diagnostic :error, :trailing_in_number, { :character => '_'.freeze }, range(@te - 1, @te) elsif digits.empty? && @num_base == 8 && version?(18) # 1.8 did not raise an error on 0o. digits = '0'.freeze elsif digits.empty? diagnostic :error, :empty_numeric elsif @num_base == 8 && (invalid_idx = digits.index(/[89]/)) invalid_s = @num_digits_s + invalid_idx diagnostic :error, :invalid_octal, nil, range(invalid_s, invalid_s + 1) end if version?(18, 19, 20) emit(:tINTEGER, digits.to_i(@num_base), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits.to_i(@num_base)) end begin p += 1 _goto_level = _out next end end end when 460 then # line 2266 "lib/parser/lexer.rl" begin @num_base = 2; @num_digits_s = p end # line 2269 "lib/parser/lexer.rl" begin @num_suffix_s = p end # line 634 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tINTEGER, chars) } end # line 2270 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin digits = tok(@num_digits_s, @num_suffix_s) if digits.end_with? '_'.freeze diagnostic :error, :trailing_in_number, { :character => '_'.freeze }, range(@te - 1, @te) elsif digits.empty? && @num_base == 8 && version?(18) # 1.8 did not raise an error on 0o. digits = '0'.freeze elsif digits.empty? diagnostic :error, :empty_numeric elsif @num_base == 8 && (invalid_idx = digits.index(/[89]/)) invalid_s = @num_digits_s + invalid_idx diagnostic :error, :invalid_octal, nil, range(invalid_s, invalid_s + 1) end if version?(18, 19, 20) emit(:tINTEGER, digits.to_i(@num_base), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits.to_i(@num_base)) end begin p += 1 _goto_level = _out next end end end when 472 then # line 2267 "lib/parser/lexer.rl" begin @num_base = 10; @num_digits_s = @ts end # line 2269 "lib/parser/lexer.rl" begin @num_suffix_s = p end # line 634 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tINTEGER, chars) } end # line 2270 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin digits = tok(@num_digits_s, @num_suffix_s) if digits.end_with? '_'.freeze diagnostic :error, :trailing_in_number, { :character => '_'.freeze }, range(@te - 1, @te) elsif digits.empty? && @num_base == 8 && version?(18) # 1.8 did not raise an error on 0o. digits = '0'.freeze elsif digits.empty? diagnostic :error, :empty_numeric elsif @num_base == 8 && (invalid_idx = digits.index(/[89]/)) invalid_s = @num_digits_s + invalid_idx diagnostic :error, :invalid_octal, nil, range(invalid_s, invalid_s + 1) end if version?(18, 19, 20) emit(:tINTEGER, digits.to_i(@num_base), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits.to_i(@num_base)) end begin p += 1 _goto_level = _out next end end end when 436 then # line 2268 "lib/parser/lexer.rl" begin @num_base = 8; @num_digits_s = @ts end # line 2269 "lib/parser/lexer.rl" begin @num_suffix_s = p end # line 634 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tINTEGER, chars) } end # line 2270 "lib/parser/lexer.rl" begin @te = p p = p - 1; begin digits = tok(@num_digits_s, @num_suffix_s) if digits.end_with? '_'.freeze diagnostic :error, :trailing_in_number, { :character => '_'.freeze }, range(@te - 1, @te) elsif digits.empty? && @num_base == 8 && version?(18) # 1.8 did not raise an error on 0o. digits = '0'.freeze elsif digits.empty? diagnostic :error, :empty_numeric elsif @num_base == 8 && (invalid_idx = digits.index(/[89]/)) invalid_s = @num_digits_s + invalid_idx diagnostic :error, :invalid_octal, nil, range(invalid_s, invalid_s + 1) end if version?(18, 19, 20) emit(:tINTEGER, digits.to_i(@num_base), @ts, @num_suffix_s) p = @num_suffix_s - 1 else @num_xfrm.call(digits.to_i(@num_base)) end begin p += 1 _goto_level = _out next end end end when 31 then # line 1 "NONE" begin @te = p+1 end # line 862 "lib/parser/lexer.rl" begin # After every heredoc was parsed, @herebody_s contains the # position of next token after all heredocs. if @herebody_s p = @herebody_s @herebody_s = nil end end # line 1567 "lib/parser/lexer.rl" begin tm = p end # line 1568 "lib/parser/lexer.rl" begin @act = 72; end when 62 then # line 1 "NONE" begin @te = p+1 end # line 1222 "lib/parser/lexer.rl" begin @sharp_s = p - 1 end # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 1738 "lib/parser/lexer.rl" begin @act = 98; end when 92 then # line 1 "NONE" begin @te = p+1 end # line 1222 "lib/parser/lexer.rl" begin @sharp_s = p - 1 end # line 1225 "lib/parser/lexer.rl" begin emit_comment(@sharp_s, p == pe ? p - 2 : p) end # line 2502 "lib/parser/lexer.rl" begin @act = 180; end when 479 then # line 1 "NONE" begin @te = p+1 end # line 2269 "lib/parser/lexer.rl" begin @num_suffix_s = p end # line 634 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tINTEGER, chars) } end # line 2302 "lib/parser/lexer.rl" begin @act = 155; end when 475 then # line 1 "NONE" begin @te = p+1 end # line 2267 "lib/parser/lexer.rl" begin @num_base = 10; @num_digits_s = @ts end # line 2269 "lib/parser/lexer.rl" begin @num_suffix_s = p end # line 634 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tINTEGER, chars) } end # line 2302 "lib/parser/lexer.rl" begin @act = 155; end when 439 then # line 1 "NONE" begin @te = p+1 end # line 2268 "lib/parser/lexer.rl" begin @num_base = 8; @num_digits_s = @ts end # line 2269 "lib/parser/lexer.rl" begin @num_suffix_s = p end # line 634 "lib/parser/lexer.rl" begin @num_xfrm = lambda { |chars| emit(:tINTEGER, chars) } end # line 2302 "lib/parser/lexer.rl" begin @act = 155; end # line 23594 "lib/parser/lexer.rb" end end end if _goto_level <= _again case _lex_to_state_actions[ @cs] when 96 then # line 1 "NONE" begin @ts = nil; end # line 23604 "lib/parser/lexer.rb" end if @cs == 0 _goto_level = _out next end p += 1 if p != pe _goto_level = _resume next end end if _goto_level <= _test_eof if p == eof if _lex_eof_trans[ @cs] > 0 _trans = _lex_eof_trans[ @cs] - 1; _goto_level = _eof_trans next; end end end if _goto_level <= _out break end end end # line 286 "lib/parser/lexer.rl" # % # Ragel creates a local variable called `testEof` but it doesn't use # it in any assignment. This dead code is here to swallow the warning. # It has no runtime cost because Ruby doesn't produce any instructions from it. if false testEof end @p = p if @token_queue.any? @token_queue.shift elsif @cs == klass.lex_error [ false, [ '$error'.freeze, range(p - 1, p) ] ] else eof = @source_pts.size [ false, [ '$eof'.freeze, range(eof, eof) ] ] end end
dedent_level()
click to toggle source
# File lib/parser/lexer.rb, line 10958 def dedent_level # We erase @dedent_level as a precaution to avoid accidentally # using a stale value. dedent_level, @dedent_level = @dedent_level, nil dedent_level end
encoding()
click to toggle source
# File lib/parser/lexer.rb, line 10908 def encoding @source_buffer.source.encoding end
pop_cmdarg()
click to toggle source
# File lib/parser/lexer.rb, line 10945 def pop_cmdarg @cmdarg = @cmdarg_stack.pop end
pop_cond()
click to toggle source
# File lib/parser/lexer.rb, line 10954 def pop_cond @cond = @cond_stack.pop end
push_cmdarg()
click to toggle source
# File lib/parser/lexer.rb, line 10940 def push_cmdarg @cmdarg_stack.push(@cmdarg) @cmdarg = StackState.new("cmdarg.#{@cmdarg_stack.count}") end
push_cond()
click to toggle source
# File lib/parser/lexer.rb, line 10949 def push_cond @cond_stack.push(@cond) @cond = StackState.new("cond.#{@cond_stack.count}") end
reset(reset_state=true)
click to toggle source
# File lib/parser/lexer.rb, line 10819 def reset(reset_state=true) # Ragel state: if reset_state # Unit tests set state prior to resetting lexer. @cs = self.class.lex_en_line_begin @cond = StackState.new('cond') @cmdarg = StackState.new('cmdarg') @cond_stack = [] @cmdarg_stack = [] end @force_utf32 = false # Set to true by some tests @source_pts = nil # @source as a codepoint array @p = 0 # stream position (saved manually in #advance) @ts = nil # token start @te = nil # token end @act = 0 # next action @stack = [] # state stack @top = 0 # state stack top pointer # Lexer state: @token_queue = [] @literal_stack = [] @eq_begin_s = nil # location of last encountered =begin @sharp_s = nil # location of last encountered # @newline_s = nil # location of last encountered newline @num_base = nil # last numeric base @num_digits_s = nil # starting position of numeric digits @num_suffix_s = nil # starting position of numeric suffix @num_xfrm = nil # numeric suffix-induced transformation @escape_s = nil # starting position of current sequence @escape = nil # last escaped sequence, as string @herebody_s = nil # starting position of current heredoc line # Ruby 1.9 ->() lambdas emit a distinct token if do/{ is # encountered after a matching closing parenthesis. @paren_nest = 0 @lambda_stack = [] # After encountering the closing line of <<~SQUIGGLY_HEREDOC, # we store the indentation level and give it out to the parser # on request. It is not possible to infer indentation level just # from the AST because escape sequences such as `\ ` or `\t` are # expanded inside the lexer, but count as non-whitespace for # indentation purposes. @dedent_level = nil # If the lexer is in `command state' (aka expr_value) # at the entry to #advance, it will transition to expr_cmdarg # instead of expr_arg at certain points. @command_start = true # True at the end of "def foo a:" @in_kwarg = false # State before =begin / =end block comment @cs_before_block_comment = self.class.lex_en_line_begin end
source_buffer=(source_buffer)
click to toggle source
# File lib/parser/lexer.rb, line 10887 def source_buffer=(source_buffer) @source_buffer = source_buffer if @source_buffer source = @source_buffer.source if source.encoding == Encoding::UTF_8 @source_pts = source.unpack('U*') else @source_pts = source.unpack('C*') end if @source_pts[0] == 0xfeff # Skip byte order mark. @p = 1 end else @source_pts = nil end end
state()
click to toggle source
# File lib/parser/lexer.rb, line 10932 def state LEX_STATES.invert.fetch(@cs, @cs) end
state=(state)
click to toggle source
# File lib/parser/lexer.rb, line 10936 def state=(state) @cs = LEX_STATES.fetch(state) end
Protected Instance Methods
arg_or_cmdarg(cmd_state)
click to toggle source
# File lib/parser/lexer.rb, line 23707 def arg_or_cmdarg(cmd_state) if cmd_state self.class.lex_en_expr_cmdarg else self.class.lex_en_expr_arg end end
diagnostic(type, reason, arguments=nil, location=range, highlights=[])
click to toggle source
# File lib/parser/lexer.rb, line 23727 def diagnostic(type, reason, arguments=nil, location=range, highlights=[]) @diagnostics.process( Parser::Diagnostic.new(type, reason, arguments, location, highlights)) end
emit(type, value = tok, s = @ts, e = @te)
click to toggle source
# File lib/parser/lexer.rb, line 23681 def emit(type, value = tok, s = @ts, e = @te) token = [ type, [ value, range(s, e) ] ] @token_queue.push(token) @tokens.push(token) if @tokens token end
emit_comment(s = @ts, e = @te)
click to toggle source
# File lib/parser/lexer.rb, line 23715 def emit_comment(s = @ts, e = @te) if @comments @comments.push(Parser::Source::Comment.new(range(s, e))) end if @tokens @tokens.push([ :tCOMMENT, [ tok(s, e), range(s, e) ] ]) end nil end
emit_do(do_block=false)
click to toggle source
# File lib/parser/lexer.rb, line 23697 def emit_do(do_block=false) if @cond.active? emit(:kDO_COND, 'do'.freeze) elsif @cmdarg.active? || do_block emit(:kDO_BLOCK, 'do'.freeze) else emit(:kDO, 'do'.freeze) end end
emit_table(table, s = @ts, e = @te)
click to toggle source
# File lib/parser/lexer.rb, line 23691 def emit_table(table, s = @ts, e = @te) value = tok(s, e) emit(table[value], value, s, e) end
encode_escape(ord)
click to toggle source
# File lib/parser/lexer.rb, line 23669 def encode_escape(ord) ord.chr.force_encoding(@source_buffer.source.encoding) end
eof_codepoint?(point)
click to toggle source
# File lib/parser/lexer.rb, line 23656 def eof_codepoint?(point) [0x04, 0x1a, 0x00].include? point end
literal()
click to toggle source
# File lib/parser/lexer.rb, line 23770 def literal @literal_stack.last end
next_state_for_literal(literal)
click to toggle source
# File lib/parser/lexer.rb, line 23742 def next_state_for_literal(literal) if literal.words? && literal.backslash_delimited? if literal.interpolate? self.class.lex_en_interp_backslash_delimited_words else self.class.lex_en_plain_backslash_delimited_words end elsif literal.words? && !literal.backslash_delimited? if literal.interpolate? self.class.lex_en_interp_words else self.class.lex_en_plain_words end elsif !literal.words? && literal.backslash_delimited? if literal.interpolate? self.class.lex_en_interp_backslash_delimited else self.class.lex_en_plain_backslash_delimited end else if literal.interpolate? self.class.lex_en_interp_string else self.class.lex_en_plain_string end end end
pop_literal()
click to toggle source
# File lib/parser/lexer.rb, line 23774 def pop_literal old_literal = @literal_stack.pop @dedent_level = old_literal.dedent_level if old_literal.type == :tREGEXP_BEG # Fetch modifiers. self.class.lex_en_regexp_modifiers else self.class.lex_en_expr_end end end
push_literal(*args)
click to toggle source
range(s = @ts, e = @te)
click to toggle source
# File lib/parser/lexer.rb, line 23677 def range(s = @ts, e = @te) Parser::Source::Range.new(@source_buffer, s, e) end
stack_pop()
click to toggle source
# File lib/parser/lexer.rb, line 23664 def stack_pop @top -= 1 @stack[@top] end
tok(s = @ts, e = @te)
click to toggle source
# File lib/parser/lexer.rb, line 23673 def tok(s = @ts, e = @te) @source_buffer.slice(s...e) end
version?(*versions)
click to toggle source
# File lib/parser/lexer.rb, line 23660 def version?(*versions) versions.include?(@version) end