diff --git a/lib/lrama/grammar.rb b/lib/lrama/grammar.rb index c295e47b..6b53d5b3 100644 --- a/lib/lrama/grammar.rb +++ b/lib/lrama/grammar.rb @@ -307,6 +307,47 @@ def nterms end def extract_references + unless initial_action.nil? + scanner = StringScanner.new(initial_action.s_value) + references = [] + + while !scanner.eos? do + start = scanner.pos + case + # $ references + # It need to wrap an identifier with brackets to use ".-" for identifiers + when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?\$/) # $$, $$ + tag = scanner[1] ? Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Tag, s_value: scanner[1]) : nil + references << [:dollar, "$", tag, start, scanner.pos - 1] + when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?(\d+)/) # $1, $2, $1 + tag = scanner[1] ? Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Tag, s_value: scanner[1]) : nil + references << [:dollar, Integer(scanner[2]), tag, start, scanner.pos - 1] + when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?([a-zA-Z_][a-zA-Z0-9_]*)/) # $foo, $expr, $program (named reference without brackets) + tag = scanner[1] ? Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Tag, s_value: scanner[1]) : nil + references << [:dollar, scanner[2], tag, start, scanner.pos - 1] + when scanner.scan(/\$(<[a-zA-Z0-9_]+>)?\[([a-zA-Z_.][-a-zA-Z0-9_.]*)\]/) # $expr.right, $expr-right, $program (named reference with brackets) + tag = scanner[1] ? Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Tag, s_value: scanner[1]) : nil + references << [:dollar, scanner[2], tag, start, scanner.pos - 1] + + # @ references + # It need to wrap an identifier with brackets to use ".-" for identifiers + when scanner.scan(/@\$/) # @$ + references << [:at, "$", nil, start, scanner.pos - 1] + when scanner.scan(/@(\d+)/) # @1 + references << [:at, Integer(scanner[1]), nil, start, scanner.pos - 1] + when scanner.scan(/@([a-zA-Z][a-zA-Z0-9_]*)/) # @foo, @expr (named reference without brackets) + references << [:at, scanner[1], nil, start, scanner.pos - 1] + when scanner.scan(/@\[([a-zA-Z_.][-a-zA-Z0-9_.]*)\]/) # @expr.right, @expr-right (named reference with brackets) + references << [:at, scanner[1], nil, start, scanner.pos - 1] + else + scanner.getch + end + end + + initial_action.token_code.references = references + build_references(initial_action.token_code) + end + @printers.each do |printer| scanner = StringScanner.new(printer.code.s_value) references = [] diff --git a/lib/lrama/new_parser.rb b/lib/lrama/new_parser.rb index 5b9f1a23..a18e127a 100644 --- a/lib/lrama/new_parser.rb +++ b/lib/lrama/new_parser.rb @@ -188,7 +188,7 @@ def build_token(type:, s_value:, line:, column:, alias_name: nil) 2, 48, :_reduce_16, 0, 53, :_reduce_17, 0, 54, :_reduce_18, - 6, 48, :_reduce_none, + 6, 48, :_reduce_19, 1, 48, :_reduce_none, 0, 57, :_reduce_21, 0, 58, :_reduce_22, @@ -516,7 +516,7 @@ def _reduce_16(val, _values, result) module_eval(<<'.,.,', 'parser.y', 20) def _reduce_17(val, _values, result) - @lexer.status = :c_declaration; @lexer.end_symbol = '}' + @lexer.status = :c_declaration; @lexer.end_symbol = '}'; @lineno.push(@lexer.line); @column.push(@lexer.col) result end .,., @@ -528,7 +528,12 @@ def _reduce_18(val, _values, result) end .,., -# reduce 19 omitted +module_eval(<<'.,.,', 'parser.y', 20) + def _reduce_19(val, _values, result) + code = build_token(type: :User_code, s_value: val[3], line: @lineno.pop, column: @column.pop); code.references = []; @grammar.initial_action = @grammar.build_code(:initial_action, code) + result + end +.,., # reduce 20 omitted diff --git a/parser.y b/parser.y index 2be9c15a..9f601011 100644 --- a/parser.y +++ b/parser.y @@ -18,7 +18,7 @@ rule | "%param" params | "%lex-param" params { val[1].each {|token| token.references = []; @grammar.lex_param = @grammar.build_code(:lex_param, token).token_code.s_value} } | "%parse-param" params { val[1].each {|token| token.references = []; @grammar.parse_param = @grammar.build_code(:parse_param, token).token_code.s_value} } - | "%initial-action" "{" {@lexer.status = :c_declaration; @lexer.end_symbol = '}'} C_DECLARATION {@lexer.status = :initial; @lexer.end_symbol = nil} "}" + | "%initial-action" "{" {@lexer.status = :c_declaration; @lexer.end_symbol = '}'; @lineno.push(@lexer.line); @column.push(@lexer.col)} C_DECLARATION {@lexer.status = :initial; @lexer.end_symbol = nil} "}" { code = build_token(type: :User_code, s_value: val[3], line: @lineno.pop, column: @column.pop); code.references = []; @grammar.initial_action = @grammar.build_code(:initial_action, code) } | ";" grammar_declaration: "%union" "{" {@lexer.status = :c_declaration; @lexer.end_symbol = '}'; @lineno.push(@lexer.line); @column.push(@lexer.col)} C_DECLARATION {@lexer.status = :initial; @lexer.end_symbol = nil} "}" { code = build_token(type: :User_code, s_value: val[3], line: @lineno.pop, column: @column.pop); code.references = []; @grammar.set_union(@grammar.build_code(:union, code), code.line) }