From 9896068726bc9d0ab866e545dc9e36433505b48a Mon Sep 17 00:00:00 2001 From: ydah Date: Fri, 4 Sep 2026 21:28:43 +0900 Subject: [PATCH] Ignore references in C literals and comments --- lib/lrama/lexer/token/user_code.rb | 22 ++++++++++++++++++- sig/generated/lrama/lexer/token/user_code.rbs | 3 +++ spec/lrama/lexer/token/user_code_spec.rb | 15 +++++++++++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/lib/lrama/lexer/token/user_code.rb b/lib/lrama/lexer/token/user_code.rb index 166f04954..ea1a178bc 100644 --- a/lib/lrama/lexer/token/user_code.rb +++ b/lib/lrama/lexer/token/user_code.rb @@ -26,7 +26,11 @@ def _references when reference = scan_reference(scanner) references << reference when scanner.scan(/\/\*/) - scanner.scan_until(/\*\//) + scanner.scan_until(/\*\//) || scanner.terminate + when scanner.scan(%r{//}) + scanner.scan_until(/\n/) || scanner.terminate + when quote = scanner.scan(/["']/) + skip_quoted_literal(scanner, quote) else scanner.getch end @@ -35,6 +39,22 @@ def _references references end + # @rbs (StringScanner scanner, String quote) -> void + def skip_quoted_literal(scanner, quote) + escaped = false + + until scanner.eos? + char = scanner.getch + if escaped + escaped = false + elsif char == "\\" + escaped = true + elsif char == quote + break + end + end + end + # @rbs (StringScanner scanner) -> Lrama::Grammar::Reference? def scan_reference(scanner) start = scanner.pos diff --git a/sig/generated/lrama/lexer/token/user_code.rbs b/sig/generated/lrama/lexer/token/user_code.rbs index a2ce8af81..b58486001 100644 --- a/sig/generated/lrama/lexer/token/user_code.rbs +++ b/sig/generated/lrama/lexer/token/user_code.rbs @@ -14,6 +14,9 @@ module Lrama # @rbs () -> Array[Lrama::Grammar::Reference] def _references: () -> Array[Lrama::Grammar::Reference] + # @rbs (StringScanner scanner, String quote) -> void + def skip_quoted_literal: (StringScanner scanner, String quote) -> void + # @rbs (StringScanner scanner) -> Lrama::Grammar::Reference? def scan_reference: (StringScanner scanner) -> Lrama::Grammar::Reference? end diff --git a/spec/lrama/lexer/token/user_code_spec.rb b/spec/lrama/lexer/token/user_code_spec.rb index 5607c6813..657905991 100644 --- a/spec/lrama/lexer/token/user_code_spec.rb +++ b/spec/lrama/lexer/token/user_code_spec.rb @@ -58,5 +58,20 @@ expect(references.count).to eq 1 expect(references[0]).to eq Lrama::Grammar::Reference.new(type: :at, name: "expr.right", ex_tag: nil, first_column: 1, last_column: 14) end + + it "ignores references in C literals and comments" do + code = <<~'C' + $1; + printf("total $2 and @2 \"done\""); + int character = '$3'; + // note $3 and @3 + $4; @4; + /* note $5 and @5 */ + C + + references = Lrama::Lexer::Token::UserCode.new(s_value: code, location: location).references + + expect(references.map { |ref| [ref.type, ref.index] }).to eq([[:dollar, 1], [:dollar, 4], [:at, 4]]) + end end end