From 2d468358a516f575d013f07801079e0906c61f0c Mon Sep 17 00:00:00 2001 From: yui-knk Date: Mon, 23 Oct 2023 09:07:23 +0900 Subject: Lrama v0.5.7 --- tool/lrama/lib/lrama/command.rb | 3 +- tool/lrama/lib/lrama/context.rb | 8 +- tool/lrama/lib/lrama/digraph.rb | 3 +- tool/lrama/lib/lrama/grammar.rb | 188 ++- tool/lrama/lib/lrama/grammar/union.rb | 4 +- tool/lrama/lib/lrama/lexer.rb | 434 ++---- tool/lrama/lib/lrama/option_parser.rb | 6 +- tool/lrama/lib/lrama/output.rb | 42 +- tool/lrama/lib/lrama/parser.rb | 2014 ++++++++++++++++++++++---- tool/lrama/lib/lrama/parser/token_scanner.rb | 56 - tool/lrama/lib/lrama/version.rb | 2 +- tool/lrama/template/bison/_yacc.h | 71 + tool/lrama/template/bison/yacc.c | 77 +- tool/lrama/template/bison/yacc.h | 74 +- 14 files changed, 2197 insertions(+), 785 deletions(-) delete mode 100644 tool/lrama/lib/lrama/parser/token_scanner.rb create mode 100644 tool/lrama/template/bison/_yacc.h (limited to 'tool') diff --git a/tool/lrama/lib/lrama/command.rb b/tool/lrama/lib/lrama/command.rb index 39e3c3665b..5d8957da8f 100644 --- a/tool/lrama/lib/lrama/command.rb +++ b/tool/lrama/lib/lrama/command.rb @@ -6,8 +6,9 @@ module Lrama Report::Duration.enable if options.trace_opts[:time] warning = Lrama::Warning.new - grammar = Lrama::Parser.new(options.y.read).parse + text = options.y.read options.y.close if options.y != STDIN + grammar = Lrama::Parser.new(text).parse states = Lrama::States.new(grammar, warning, trace_state: (options.trace_opts[:automaton] || options.trace_opts[:closure])) states.compute context = Lrama::Context.new(states) diff --git a/tool/lrama/lib/lrama/context.rb b/tool/lrama/lib/lrama/context.rb index da70bf1542..3d05c1f36e 100644 --- a/tool/lrama/lib/lrama/context.rb +++ b/tool/lrama/lib/lrama/context.rb @@ -170,7 +170,7 @@ module Lrama return a end - # Mapping from rule number to lenght of RHS. + # Mapping from rule number to length of RHS. # Dummy rule is appended as the first element whose value is 0 # because 0 means error in yydefact. def yyr2 @@ -214,7 +214,7 @@ module Lrama (rule_id + 1) * -1 end - # Symbol number is assinged to term first then nterm. + # Symbol number is assigned to term first then nterm. # This method calculates sequence_number for nterm. def nterm_number_to_sequence_number(nterm_number) nterm_number - @states.terms.count @@ -259,7 +259,7 @@ module Lrama actions[conflict.symbol.number] = ErrorActionNumber end - # If default_reduction_rule, replase default_reduction_rule in + # If default_reduction_rule, replace default_reduction_rule in # actions with zero. if state.default_reduction_rule actions.map! do |e| @@ -272,7 +272,7 @@ module Lrama end # If no default_reduction_rule, default behavior is an - # error then replase ErrorActionNumber with zero. + # error then replace ErrorActionNumber with zero. if !state.default_reduction_rule actions.map! do |e| if e == ErrorActionNumber diff --git a/tool/lrama/lib/lrama/digraph.rb b/tool/lrama/lib/lrama/digraph.rb index c48b3f4041..bbaa86019f 100644 --- a/tool/lrama/lib/lrama/digraph.rb +++ b/tool/lrama/lib/lrama/digraph.rb @@ -40,8 +40,7 @@ module Lrama end if @h[x] == d - while true do - z = @stack.pop + while (z = @stack.pop) do @h[z] = Float::INFINITY break if z == x @result[z] = @result[x] # F (Top of S) = F x diff --git a/tool/lrama/lib/lrama/grammar.rb b/tool/lrama/lib/lrama/grammar.rb index 81df399682..91685530a0 100644 --- a/tool/lrama/lib/lrama/grammar.rb +++ b/tool/lrama/lib/lrama/grammar.rb @@ -1,3 +1,5 @@ +require "strscan" + require "lrama/grammar/auxiliary" require "lrama/grammar/code" require "lrama/grammar/error_token" @@ -306,6 +308,188 @@ module Lrama @nterms ||= @symbols.select(&:nterm?) 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 = [] + + 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 + + printer.code.token_code.references = references + build_references(printer.code.token_code) + end + + @error_tokens.each do |error_token| + scanner = StringScanner.new(error_token.code.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 + + error_token.code.token_code.references = references + build_references(error_token.code.token_code) + end + + @_rules.each do |lhs, rhs, _| + rhs.each_with_index do |token, index| + next if token.class == Lrama::Grammar::Symbol || token.type != Lrama::Lexer::Token::User_code + + scanner = StringScanner.new(token.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] + + when scanner.scan(/\/\*/) + scanner.scan_until(/\*\//) + else + scanner.getch + end + end + + token.references = references + token.numberize_references(lhs, rhs) + build_references(token) + end + end + end + + def create_token(type, s_value, line, column) + t = Token.new(type: type, s_value: s_value) + t.line = line + t.column = column + + return t + end + private def find_nterm_by_id!(id) @@ -470,7 +654,9 @@ module Lrama # Fill #number and #token_id def fill_symbol_number - # TODO: why start from 256 + # Character literal in grammar file has + # token id corresponding to ASCII code by default, + # so start token_id from 256. token_id = 256 # YYEMPTY = -2 diff --git a/tool/lrama/lib/lrama/grammar/union.rb b/tool/lrama/lib/lrama/grammar/union.rb index 978cebf22d..854bffb5c1 100644 --- a/tool/lrama/lib/lrama/grammar/union.rb +++ b/tool/lrama/lib/lrama/grammar/union.rb @@ -2,8 +2,8 @@ module Lrama class Grammar class Union < Struct.new(:code, :lineno, keyword_init: true) def braces_less_code - # Remove braces - code.s_value[1..-2] + # Braces is already removed by lexer + code.s_value end end end diff --git a/tool/lrama/lib/lrama/lexer.rb b/tool/lrama/lib/lrama/lexer.rb index 72ce90195f..926606f3b9 100644 --- a/tool/lrama/lib/lrama/lexer.rb +++ b/tool/lrama/lib/lrama/lexer.rb @@ -1,346 +1,174 @@ require "strscan" -require "lrama/report/duration" require "lrama/lexer/token" module Lrama - # Lexer for parse.y class Lexer - include Lrama::Report::Duration - - # States - # - # See: https://www.gnu.org/software/bison/manual/html_node/Grammar-Outline.html - Initial = 0 - Prologue = 1 - BisonDeclarations = 2 - GrammarRules = 3 - Epilogue = 4 - - # Token types - - attr_reader :prologue, :bison_declarations, :grammar_rules, :epilogue, - :bison_declarations_tokens, :grammar_rules_tokens + attr_accessor :status + attr_accessor :end_symbol + + SYMBOLS = %w(%{ %} %% { } \[ \] : \| ;) + PERCENT_TOKENS = %w( + %union + %token + %type + %left + %right + %nonassoc + %expect + %define + %require + %printer + %lex-param + %parse-param + %initial-action + %precedence + %prec + %error-token + ) def initialize(text) - @text = text - @state = Initial - # Array of texts - @prologue = [] - @bison_declarations = [] - @grammar_rules = [] - @epilogue = [] - - @bison_declarations_tokens = [] - @grammar_rules_tokens = [] - - @debug = false + @scanner = StringScanner.new(text) + @head = @scanner.pos + @line = 1 + @status = :initial + @end_symbol = nil + end - report_duration(:lex) do - lex_text - lex_bison_declarations_tokens - lex_grammar_rules_tokens + def next_token + case @status + when :initial + lex_token + when :c_declaration + lex_c_code end end - private - - def create_token(type, s_value, line, column) - t = Token.new(type: type, s_value: s_value) - t.line = line - t.column = column - - return t + def line + @line end - # TODO: Remove this - def lex_text - @text.each_line.with_index(1) do |string, lineno| - case @state - when Initial - # Skip until "%{" - if string == "%{\n" - @state = Prologue - @prologue << ["", lineno] - next - end - when Prologue - # Between "%{" and "%}" - if string == "%}\n" - @state = BisonDeclarations - @prologue << ["", lineno] - next - end - - @prologue << [string, lineno] - when BisonDeclarations - if string == "%%\n" - @state = GrammarRules - next - end - - @bison_declarations << [string, lineno] - when GrammarRules - # Between "%%" and "%%" - if string == "%%\n" - @state = Epilogue - next - end - - @grammar_rules << [string, lineno] - when Epilogue - @epilogue << [string, lineno] - else - raise "Unknown state: #{@state}" - end - end + def column + @scanner.pos - @head end - # See: - # * https://www.gnu.org/software/bison/manual/html_node/Decl-Summary.html - # * https://www.gnu.org/software/bison/manual/html_node/Symbol-Decls.html - # * https://www.gnu.org/software/bison/manual/html_node/Empty-Rules.html - def lex_common(lines, tokens) - line = lines.first[1] - column = 0 - ss = StringScanner.new(lines.map(&:first).join) - - while !ss.eos? do + def lex_token + while !@scanner.eos? do case - when ss.scan(/\n/) - line += 1 - column = ss.pos - when ss.scan(/\s+/) - # skip - when ss.scan(/;/) - tokens << create_token(Token::Semicolon, ss[0], line, ss.pos - column) - when ss.scan(/\|/) - tokens << create_token(Token::Bar, ss[0], line, ss.pos - column) - when ss.scan(/(\d+)/) - tokens << create_token(Token::Number, Integer(ss[0]), line, ss.pos - column) - when ss.scan(/(<[a-zA-Z0-9_]+>)/) - tokens << create_token(Token::Tag, ss[0], line, ss.pos - column) - when ss.scan(/([a-zA-Z_.][-a-zA-Z0-9_.]*)\[([a-zA-Z_.][-a-zA-Z0-9_.]*)\]\s*:/) - tokens << create_token(Token::Ident_Colon, ss[1], line, ss.pos - column) - tokens << create_token(Token::Named_Ref, ss[2], line, ss.pos - column) - when ss.scan(/([a-zA-Z_.][-a-zA-Z0-9_.]*)\s*:/) - tokens << create_token(Token::Ident_Colon, ss[1], line, ss.pos - column) - when ss.scan(/([a-zA-Z_.][-a-zA-Z0-9_.]*)/) - tokens << create_token(Token::Ident, ss[0], line, ss.pos - column) - when ss.scan(/\[([a-zA-Z_.][-a-zA-Z0-9_.]*)\]/) - tokens << create_token(Token::Named_Ref, ss[1], line, ss.pos - column) - when ss.scan(/%expect/) - tokens << create_token(Token::P_expect, ss[0], line, ss.pos - column) - when ss.scan(/%define/) - tokens << create_token(Token::P_define, ss[0], line, ss.pos - column) - when ss.scan(/%printer/) - tokens << create_token(Token::P_printer, ss[0], line, ss.pos - column) - when ss.scan(/%error-token/) - tokens << create_token(Token::P_error_token, ss[0], line, ss.pos - column) - when ss.scan(/%lex-param/) - tokens << create_token(Token::P_lex_param, ss[0], line, ss.pos - column) - when ss.scan(/%parse-param/) - tokens << create_token(Token::P_parse_param, ss[0], line, ss.pos - column) - when ss.scan(/%initial-action/) - tokens << create_token(Token::P_initial_action, ss[0], line, ss.pos - column) - when ss.scan(/%union/) - tokens << create_token(Token::P_union, ss[0], line, ss.pos - column) - when ss.scan(/%token/) - tokens << create_token(Token::P_token, ss[0], line, ss.pos - column) - when ss.scan(/%type/) - tokens << create_token(Token::P_type, ss[0], line, ss.pos - column) - when ss.scan(/%nonassoc/) - tokens << create_token(Token::P_nonassoc, ss[0], line, ss.pos - column) - when ss.scan(/%left/) - tokens << create_token(Token::P_left, ss[0], line, ss.pos - column) - when ss.scan(/%right/) - tokens << create_token(Token::P_right, ss[0], line, ss.pos - column) - when ss.scan(/%precedence/) - tokens << create_token(Token::P_precedence, ss[0], line, ss.pos - column) - when ss.scan(/%prec/) - tokens << create_token(Token::P_prec, ss[0], line, ss.pos - column) - when ss.scan(/{/) - token, line = lex_user_code(ss, line, ss.pos - column, lines) - tokens << token - when ss.scan(/"/) - string, line = lex_string(ss, "\"", line, lines) - token = create_token(Token::String, string, line, ss.pos - column) - tokens << token - when ss.scan(/\/\*/) - # TODO: Need to keep comment? - line = lex_comment(ss, line, lines, "") - when ss.scan(/\/\//) - line = lex_line_comment(ss, line, "") - when ss.scan(/'(.)'/) - tokens << create_token(Token::Char, ss[0], line, ss.pos - column) - when ss.scan(/'\\(.)'/) # '\\', '\t' - tokens << create_token(Token::Char, ss[0], line, ss.pos - column) - when ss.scan(/'\\(\d+)'/) # '\13' - tokens << create_token(Token::Char, ss[0], line, ss.pos - column) - when ss.scan(/%empty/) - # skip + when @scanner.scan(/\n/) + newline + when @scanner.scan(/\s+/) + # noop + when @scanner.scan(/\/\*/) + lex_comment + when @scanner.scan(/\/\//) + @scanner.scan_until(/\n/) + newline + when @scanner.scan(/%empty/) + # noop else - l = line - lines.first[1] - split = ss.string.split("\n") - col = ss.pos - split[0...l].join("\n").length - raise "Parse error (unknown token): #{split[l]} \"#{ss.string[ss.pos]}\" (#{line}: #{col})" + break end end - end - def lex_bison_declarations_tokens - lex_common(@bison_declarations, @bison_declarations_tokens) + @head_line = line + @head_column = column + + case + when @scanner.eos? + return + when @scanner.scan(/#{SYMBOLS.join('|')}/) + return [@scanner.matched, @scanner.matched] + when @scanner.scan(/#{PERCENT_TOKENS.join('|')}/) + return [@scanner.matched, @scanner.matched] + when @scanner.scan(/<\w+>/) + return [:TAG, build_token(type: Token::Tag, s_value: @scanner.matched)] + when @scanner.scan(/'.'/) + return [:CHARACTER, build_token(type: Token::Char, s_value: @scanner.matched)] + when @scanner.scan(/'\\\\'|'\\b'|'\\t'|'\\f'|'\\r'|'\\n'|'\\v'|'\\13'/) + return [:CHARACTER, build_token(type: Token::Char, s_value: @scanner.matched)] + when @scanner.scan(/"/) + return [:STRING, %Q("#{@scanner.scan_until(/"/)})] + when @scanner.scan(/\d+/) + return [:INTEGER, Integer(@scanner.matched)] + when @scanner.scan(/([a-zA-Z_.][-a-zA-Z0-9_.]*)/) + token = build_token(type: Token::Ident, s_value: @scanner.matched) + type = + if @scanner.check(/\s*(\[\s*[a-zA-Z_.][-a-zA-Z0-9_.]*\s*\])?\s*:/) + :IDENT_COLON + else + :IDENTIFIER + end + return [type, token] + else + raise + end end - def lex_user_code(ss, line, column, lines) - first_line = line - first_column = column - debug("Enter lex_user_code: #{line}") - brace_count = 1 - str = "{" - # Array of [type, $n, tag, first column, last column] - # TODO: Is it better to keep string, like "$$", and use gsub? - references = [] - - while !ss.eos? do + def lex_c_code + nested = 0 + code = '' + while !@scanner.eos? do case - when ss.scan(/\n/) - line += 1 - when ss.scan(/"/) - string, line = lex_string(ss, "\"", line, lines) - str << string - next - when ss.scan(/'/) - string, line = lex_string(ss, "'", line, lines) - str << string - next - - # $ references - # It need to wrap an identifier with brackets to use ".-" for identifiers - when ss.scan(/\$(<[a-zA-Z0-9_]+>)?\$/) # $$, $$ - tag = ss[1] ? create_token(Token::Tag, ss[1], line, str.length) : nil - references << [:dollar, "$", tag, str.length, str.length + ss[0].length - 1] - when ss.scan(/\$(<[a-zA-Z0-9_]+>)?(\d+)/) # $1, $2, $1 - tag = ss[1] ? create_token(Token::Tag, ss[1], line, str.length) : nil - references << [:dollar, Integer(ss[2]), tag, str.length, str.length + ss[0].length - 1] - when ss.scan(/\$(<[a-zA-Z0-9_]+>)?([a-zA-Z_][a-zA-Z0-9_]*)/) # $foo, $expr, $program (named reference without brackets) - tag = ss[1] ? create_token(Token::Tag, ss[1], line, str.length) : nil - references << [:dollar, ss[2], tag, str.length, str.length + ss[0].length - 1] - when ss.scan(/\$(<[a-zA-Z0-9_]+>)?\[([a-zA-Z_.][-a-zA-Z0-9_.]*)\]/) # $expr.right, $expr-right, $program (named reference with brackets) - tag = ss[1] ? create_token(Token::Tag, ss[1], line, str.length) : nil - references << [:dollar, ss[2], tag, str.length, str.length + ss[0].length - 1] - - # @ references - # It need to wrap an identifier with brackets to use ".-" for identifiers - when ss.scan(/@\$/) # @$ - references << [:at, "$", nil, str.length, str.length + ss[0].length - 1] - when ss.scan(/@(\d+)/) # @1 - references << [:at, Integer(ss[1]), nil, str.length, str.length + ss[0].length - 1] - when ss.scan(/@([a-zA-Z][a-zA-Z0-9_]*)/) # @foo, @expr (named reference without brackets) - references << [:at, ss[1], nil, str.length, str.length + ss[0].length - 1] - when ss.scan(/@\[([a-zA-Z_.][-a-zA-Z0-9_.]*)\]/) # @expr.right, @expr-right (named reference with brackets) - references << [:at, ss[1], nil, str.length, str.length + ss[0].length - 1] - - when ss.scan(/{/) - brace_count += 1 - when ss.scan(/}/) - brace_count -= 1 - - debug("Return lex_user_code: #{line}") - if brace_count == 0 - str << ss[0] - user_code = Token.new(type: Token::User_code, s_value: str.freeze) - user_code.line = first_line - user_code.column = first_column - user_code.references = references - return [user_code, line] + when @scanner.scan(/{/) + code += @scanner.matched + nested += 1 + when @scanner.scan(/}/) + if nested == 0 && @end_symbol == '}' + @scanner.unscan + return [:C_DECLARATION, build_token(type: Token::User_code, s_value: code, references: [])] + else + code += @scanner.matched + nested -= 1 end - when ss.scan(/\/\*/) - str << ss[0] - line = lex_comment(ss, line, lines, str) - when ss.scan(/\/\//) - str << ss[0] - line = lex_line_comment(ss, line, str) + when @scanner.check(/#{@end_symbol}/) + return [:C_DECLARATION, build_token(type: Token::User_code, s_value: code, references: [])] + when @scanner.scan(/\n/) + code += @scanner.matched + newline + when @scanner.scan(/"/) + matched = @scanner.scan_until(/"/) + code += %Q("#{matched}) + @line += matched.count("\n") + when @scanner.scan(/'/) + matched = @scanner.scan_until(/'/) + code += %Q('#{matched}) else - # noop, just consume char - str << ss.getch - next + code += @scanner.getch end - - str << ss[0] end - - # Reach to end of input but brace does not match - l = line - lines.first[1] - raise "Parse error (brace mismatch): #{ss.string.split("\n")[l]} \"#{ss.string[ss.pos]}\" (#{line}: #{ss.pos})" + raise end - def lex_string(ss, terminator, line, lines) - debug("Enter lex_string: #{line}") - - str = terminator.dup - - while (c = ss.getch) do - str << c - - case c - when "\n" - line += 1 - when terminator - debug("Return lex_string: #{line}") - return [str, line] - else - # noop - end - end - - # Reach to end of input but quote does not match - l = line - lines.first[1] - raise "Parse error (quote mismatch): #{ss.string.split("\n")[l]} \"#{ss.string[ss.pos]}\" (#{line}: #{ss.pos})" - end + private - # /* */ style comment - def lex_comment(ss, line, lines, str) - while !ss.eos? do + def lex_comment + while !@scanner.eos? do case - when ss.scan(/\n/) - line += 1 - when ss.scan(/\*\//) - return line + when @scanner.scan(/\n/) + @line += 1 + @head = @scanner.pos + 1 + when @scanner.scan(/\*\//) + return else - str << ss.getch - next + @scanner.getch end - - str << ss[0] end - - # Reach to end of input but quote does not match - l = line - lines.first[1] - raise "Parse error (comment mismatch): #{ss.string.split("\n")[l]} \"#{ss.string[ss.pos]}\" (#{line}: #{ss.pos})" end - # // style comment - def lex_line_comment(ss, line, str) - while !ss.eos? do - case - when ss.scan(/\n/) - return line + 1 - else - str << ss.getch - next - end + def build_token(type:, s_value:, **options) + token = Token.new(type: type, s_value: s_value) + token.line = @head_line + token.column = @head_column + options.each do |attr, value| + token.public_send("#{attr}=", value) end - line # Reach to end of input - end - - def lex_grammar_rules_tokens - lex_common(@grammar_rules, @grammar_rules_tokens) + token end - def debug(msg) - return unless @debug - puts "#{msg}\n" + def newline + @line += 1 + @head = @scanner.pos + 1 end end end diff --git a/tool/lrama/lib/lrama/option_parser.rb b/tool/lrama/lib/lrama/option_parser.rb index d8ed62ee07..86e482912b 100644 --- a/tool/lrama/lib/lrama/option_parser.rb +++ b/tool/lrama/lib/lrama/option_parser.rb @@ -52,12 +52,16 @@ module Lrama Usage: lrama [options] FILE BANNER o.separator '' + o.separator 'STDIN mode:' + o.separator 'lrama [options] - FILE read grammar from STDIN' + o.separator '' o.separator 'Tuning the Parser:' o.on('-S', '--skeleton=FILE', 'specify the skeleton to use') {|v| @options.skeleton = v } o.on('-t', 'reserved, do nothing') { } o.separator '' o.separator 'Output:' - o.on('-h', '--header=[FILE]', 'also produce a header file named FILE') {|v| @options.header = true; @options.header_file = v } + o.on('-H', '--header=[FILE]', 'also produce a header file named FILE') {|v| @options.header = true; @options.header_file = v } + o.on('-h=[FILE]', 'also produce a header file named FILE (deprecated)') {|v| @options.header = true; @options.header_file = v } o.on('-d', 'also produce a header file') { @options.header = true } o.on('-r', '--report=THINGS', Array, 'also produce details on the automaton') {|v| @report = v } o.on('--report-file=FILE', 'also produce details on the automaton output to a file named FILE') {|v| @options.report_file = v } diff --git a/tool/lrama/lib/lrama/output.rb b/tool/lrama/lib/lrama/output.rb index 2dcdae7b42..95747ce4ea 100644 --- a/tool/lrama/lib/lrama/output.rb +++ b/tool/lrama/lib/lrama/output.rb @@ -7,7 +7,7 @@ module Lrama extend Forwardable include Report::Duration - attr_reader :grammar_file_path, :context, :grammar, :error_recovery + attr_reader :grammar_file_path, :context, :grammar, :error_recovery, :include_header def_delegators "@context", :yyfinal, :yylast, :yyntokens, :yynnts, :yynrules, :yynstates, :yymaxutok, :yypact_ninf, :yytable_ninf @@ -28,6 +28,7 @@ module Lrama @context = context @grammar = grammar @error_recovery = error_recovery + @include_header = header_file_path ? header_file_path.sub("./", "") : nil end if ERB.instance_method(:initialize).parameters.last.first == :key @@ -40,11 +41,8 @@ module Lrama end end - def eval_template(file, path) - erb = self.class.erb(File.read(file)) - erb.filename = file - tmp = erb.result_with_hash(context: @context, output: self) - replace_special_variables(tmp, path) + def render_partial(file) + render_template(partial_file(file)) end def render @@ -143,7 +141,7 @@ module Lrama str << <<-STR case #{sym.enum_name}: /* #{sym.comment} */ #line #{sym.printer.lineno} "#{@grammar_file_path}" - #{sym.printer.translated_code(sym.tag)} + {#{sym.printer.translated_code(sym.tag)}} #line [@oline@] [@ofile@] break; @@ -160,7 +158,7 @@ module Lrama <<-STR #{comment} #line #{@grammar.initial_action.line} "#{@grammar_file_path}" - #{@grammar.initial_action.translated_code} + {#{@grammar.initial_action.translated_code}} STR end @@ -173,7 +171,7 @@ module Lrama str << <<-STR case #{sym.enum_name}: /* #{sym.comment} */ #line #{sym.error_token.lineno} "#{@grammar_file_path}" - #{sym.error_token.translated_code(sym.tag)} + {#{sym.error_token.translated_code(sym.tag)}} #line [@oline@] [@ofile@] break; @@ -190,14 +188,13 @@ module Lrama @context.states.rules.each do |rule| next unless rule.code - rule = rule code = rule.code spaces = " " * (code.column - 1) str << <<-STR case #{rule.id + 1}: /* #{rule.as_comment} */ #line #{code.line} "#{@grammar_file_path}" -#{spaces}#{rule.translated_code} +#{spaces}{#{rule.translated_code}} #line [@oline@] [@ofile@] break; @@ -212,14 +209,14 @@ module Lrama str end - def omit_braces_and_blanks(param) - param[1..-2].strip + def omit_blanks(param) + param.strip end # b4_parse_param def parse_param if @grammar.parse_param - omit_braces_and_blanks(@grammar.parse_param) + omit_blanks(@grammar.parse_param) else "" end @@ -227,7 +224,7 @@ module Lrama def lex_param if @grammar.lex_param - omit_braces_and_blanks(@grammar.lex_param) + omit_blanks(@grammar.lex_param) else "" end @@ -354,6 +351,17 @@ module Lrama private + def eval_template(file, path) + tmp = render_template(file) + replace_special_variables(tmp, path) + end + + def render_template(file) + erb = self.class.erb(File.read(file)) + erb.filename = file + erb.result_with_hash(context: @context, output: self) + end + def template_file File.join(template_dir, @template_name) end @@ -362,6 +370,10 @@ module Lrama File.join(template_dir, "bison/yacc.h") end + def partial_file(file) + File.join(template_dir, file) + end + def template_dir File.expand_path("../../../template", __FILE__) end diff --git a/tool/lrama/lib/lrama/parser.rb b/tool/lrama/lib/lrama/parser.rb index 18e2ef033e..82bd90c32c 100644 --- a/tool/lrama/lib/lrama/parser.rb +++ b/tool/lrama/lib/lrama/parser.rb @@ -1,293 +1,1797 @@ -require "lrama/report/duration" -require "lrama/parser/token_scanner" +# +# DO NOT MODIFY!!!! +# This file is automatically generated by Racc 1.7.1 +# from Racc grammar file "". +# + +###### racc/parser.rb begin +unless $".find {|p| p.end_with?('/racc/parser.rb')} +$".push "#{__dir__}/racc/parser.rb" +self.class.module_eval(<<'...end racc/parser.rb/module_eval...', 'racc/parser.rb', 1) +# frozen_string_literal: false +#-- +# Copyright (c) 1999-2006 Minero Aoki +# +# This program is free software. +# You can distribute/modify this program under the same terms of ruby. +# +# As a special exception, when this code is copied by Racc +# into a Racc output file, you may use that output file +# without restriction. +#++ + +unless $".find {|p| p.end_with?('/racc/info.rb')} +$".push "#{__dir__}/racc/info.rb" +#-- +# +# +# +# Copyright (c) 1999-2006 Minero Aoki +# +# This program is free software. +# You can distribute/modify this program under the same terms of ruby. +# see the file "COPYING". +# +#++ + +module Racc + VERSION = '1.7.1' + Version = VERSION + Copyright = 'Copyright (c) 1999-2006 Minero Aoki' +end + +end + + +unless defined?(NotImplementedError) + NotImplementedError = NotImplementError # :nodoc: +end + +module Racc + class ParseError < StandardError; end +end +unless defined?(::ParseError) + ParseError = Racc::ParseError # :nodoc: +end + +# Racc is a LALR(1) parser generator. +# It is written in Ruby itself, and generates Ruby programs. +# +# == Command-line Reference +# +# racc [-ofilename] [--output-file=filename] +# [-erubypath] [--executable=rubypath] +# [-v] [--verbose] +# [-Ofilename] [--log-file=filename] +# [-g] [--debug] +# [-E] [--embedded] +# [-l] [--no-line-convert] +# [-c] [--line-convert-all] +# [-a] [--no-omit-actions] +# [-C] [--check-only] +# [-S] [--output-status] +# [--version] [--copyright] [--help] grammarfile +# +# [+grammarfile+] +# Racc grammar file. Any extension is permitted. +# [-o+outfile+, --output-file=+outfile+] +# A filename for output. default is <+filename+>.tab.rb +# [-O+filename+, --log-file=+filename+] +# Place logging output in file +filename+. +# Default log file name is <+filename+>.output. +# [-e+rubypath+, --executable=+rubypath+] +# output executable file(mode 755). where +path+ is the Ruby interpreter. +# [-v, --verbose] +# verbose mode. create +filename+.output file, like yacc's y.output file. +# [-g, --debug] +# add debug code to parser class. To display debuggin information, +# use this '-g' option and set @yydebug true in parser class. +# [-E, --embedded] +# Output parser which doesn't need runtime files (racc/parser.rb). +# [-C, --check-only] +# Check syntax of racc grammar file and quit. +# [-S, --output-status] +# Print messages time to time while compiling. +# [-l, --no-line-convert] +# turns off line number converting. +# [-c, --line-convert-all] +# Convert line number of actions, inner, header and footer. +# [-a, --no-omit-actions] +# Call all actions, even if an action is empty. +# [--version] +# print Racc version and quit. +# [--copyright] +# Print copyright and quit. +# [--help] +# Print usage and quit. +# +# == Generating Parser Using Racc +# +# To compile Racc grammar file, simply type: +# +# $ racc parse.y +# +# This creates Ruby script file "parse.tab.y". The -o option can change the output filename. +# +# == Writing A Racc Grammar File +# +# If you want your own parser, you have to write a grammar file. +# A grammar file contains the name of your parser class, grammar for the parser, +# user code, and anything else. +# When writing a grammar file, yacc's knowledge is helpful. +# If you have not used yacc before, Racc is not too difficult. +# +# Here's an example Racc grammar file. +# +# class Calcparser +# rule +# target: exp { print val[0] } +# +# exp: exp '+' exp +# | exp '*' exp +# | '(' exp ')' +# | NUMBER +# end +# +# Racc grammar files resemble yacc files. +# But (of course), this is Ruby code. +# yacc's $$ is the 'result', $0, $1... is +# an array called 'val', and $-1, $-2... is an array called '_values'. +# +# See the {Grammar File Reference}[rdoc-ref:lib/racc/rdoc/grammar.en.rdoc] for +# more information on grammar files. +# +# == Parser +# +# Then you must prepare the parse entry method. There are two types of +# parse methods in Racc, Racc::Parser#do_parse and Racc::Parser#yyparse +# +# Racc::Parser#do_parse is simple. +# +# It's yyparse() of yacc, and Racc::Parser#next_token is yylex(). +# This method must returns an array like [TOKENSYMBOL, ITS_VALUE]. +# EOF is [false, false]. +# (TOKENSYMBOL is a Ruby symbol (taken from String#intern) by default. +# If you want to change this, see the grammar reference. +# +# Racc::Parser#yyparse is little complicated, but useful. +# It does not use Racc::Parser#next_token, instead it gets tokens from any iterator. +# +# For example, yyparse(obj, :scan) causes +# calling +obj#scan+, and you can return tokens by yielding them from +obj#scan+. +# +# == Debugging +# +# When debugging, "-v" or/and the "-g" option is helpful. +# +# "-v" creates verbose log file (.output). +# "-g" creates a "Verbose Parser". +# Verbose Parser prints the internal status when parsing. +# But it's _not_ automatic. +# You must use -g option and set +@yydebug+ to +true+ in order to get output. +# -g option only creates the verbose parser. +# +# === Racc reported syntax error. +# +# Isn't there too many "end"? +# grammar of racc file is changed in v0.10. +# +# Racc does not use '%' mark, while yacc uses huge number of '%' marks.. +# +# === Racc reported "XXXX conflicts". +# +# Try "racc -v xxxx.y". +# It causes producing racc's internal log file, xxxx.output. +# +# === Generated parsers does not work correctly +# +# Try "racc -g xxxx.y". +# This command let racc generate "debugging parser". +# Then set @yydebug=true in your parser. +# It produces a working log of your parser. +# +# == Re-distributing Racc runtime +# +# A parser, which is created by Racc, requires the Racc runtime module; +# racc/parser.rb. +# +# Ruby 1.8.x comes with Racc runtime module, +# you need NOT distribute Racc runtime files. +# +# If you want to include the Racc runtime module with your parser. +# This can be done by using '-E' option: +# +# $ racc -E -omyparser.rb myparser.y +# +# This command creates myparser.rb which `includes' Racc runtime. +# Only you must do is to distribute your parser file (myparser.rb). +# +# Note: parser.rb is ruby license, but your parser is not. +# Your own parser is completely yours. +module Racc + + unless defined?(Racc_No_Extensions) + Racc_No_Extensions = false # :nodoc: + end -module Lrama - # Parser for parse.y, generates a grammar class Parser - include Lrama::Report::Duration - T = Lrama::Lexer::Token + Racc_Runtime_Version = ::Racc::VERSION + Racc_Runtime_Core_Version_R = ::Racc::VERSION + + begin + if Object.const_defined?(:RUBY_ENGINE) and RUBY_ENGINE == 'jruby' + require 'jruby' + require 'racc/cparse-jruby.jar' + com.headius.racc.Cparse.new.load(JRuby.runtime, false) + else + require 'racc/cparse' + end + + unless new.respond_to?(:_racc_do_parse_c, true) + raise LoadError, 'old cparse.so' + end + if Racc_No_Extensions + raise LoadError, 'selecting ruby version of racc runtime core' + end + + Racc_Main_Parsing_Routine = :_racc_do_parse_c # :nodoc: + Racc_YY_Parse_Method = :_racc_yyparse_c # :nodoc: + Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_C # :nodoc: + Racc_Runtime_Type = 'c' # :nodoc: + rescue LoadError + Racc_Main_Parsing_Routine = :_racc_do_parse_rb + Racc_YY_Parse_Method = :_racc_yyparse_rb + Racc_Runtime_Core_Version = Racc_Runtime_Core_Version_R + Racc_Runtime_Type = 'ruby' + end - def initialize(text) - @text = text + def Parser.racc_runtime_type # :nodoc: + Racc_Runtime_Type end - def parse - report_duration(:parse) do - lexer = Lexer.new(@text) - grammar = Grammar.new - process_prologue(grammar, lexer) - parse_bison_declarations(TokenScanner.new(lexer.bison_declarations_tokens), grammar) - parse_grammar_rules(TokenScanner.new(lexer.grammar_rules_tokens), grammar) - process_epilogue(grammar, lexer) - grammar.prepare - grammar.compute_nullable - grammar.compute_first_set - grammar.validate! - - grammar + def _racc_setup + @yydebug = false unless self.class::Racc_debug_parser + @yydebug = false unless defined?(@yydebug) + if @yydebug + @racc_debug_out = $stderr unless defined?(@racc_debug_out) + @racc_debug_out ||= $stderr end + arg = self.class::Racc_arg + arg[13] = true if arg.size < 14 + arg end - private + def _racc_init_sysvars + @racc_state = [0] + @racc_tstack = [] + @racc_vstack = [] - def process_prologue(grammar, lexer) - grammar.prologue_first_lineno = lexer.prologue.first[1] if lexer.prologue.first - grammar.prologue = lexer.prologue.map(&:first).join + @racc_t = nil + @racc_val = nil + + @racc_read_next = true + + @racc_user_yyerror = false + @racc_error_status = 0 + end + + # The entry point of the parser. This method is used with #next_token. + # If Racc wants to get token (and its value), calls next_token. + # + # Example: + # def parse + # @q = [[1,1], + # [2,2], + # [3,3], + # [false, '$']] + # do_parse + # end + # + # def next_token + # @q.shift + # end + class_eval <<~RUBY, __FILE__, __LINE__ + 1 + def do_parse + #{Racc_Main_Parsing_Routine}(_racc_setup(), false) end + RUBY - def process_epilogue(grammar, lexer) - grammar.epilogue_first_lineno = lexer.epilogue.first[1] if lexer.epilogue.first - grammar.epilogue = lexer.epilogue.map(&:first).join + # The method to fetch next token. + # If you use #do_parse method, you must implement #next_token. + # + # The format of return value is [TOKEN_SYMBOL, VALUE]. + # +token-symbol+ is represented by Ruby's symbol by default, e.g. :IDENT + # for 'IDENT'. ";" (String) for ';'. + # + # The final symbol (End of file) must be false. + def next_token + raise NotImplementedError, "#{self.class}\#next_token is not defined" end - def parse_bison_declarations(ts, grammar) - precedence_number = 0 - - while !ts.eots? do - case ts.current_type - when T::P_expect - ts.next - grammar.expect = ts.consume!(T::Number).s_value - when T::P_define - ts.next - # Ignore - ts.consume_multi(T::Ident) - when T::P_printer - lineno = ts.current_token.line - ts.next - code = ts.consume!(T::User_code) - code = grammar.build_code(:printer, code) - ident_or_tags = ts.consume_multi(T::Ident, T::Tag) - grammar.add_printer(ident_or_tags: ident_or_tags, code: code, lineno: lineno) - when T::P_error_token - lineno = ts.current_token.line - ts.next - code = ts.consume!(T::User_code) - code = grammar.build_code(:printer, code) - ident_or_tags = ts.consume_multi(T::Ident, T::Tag) - grammar.add_error_token(ident_or_tags: ident_or_tags, code: code, lineno: lineno) - when T::P_lex_param - ts.next - code = ts.consume!(T::User_code) - code = grammar.build_code(:lex_param, code) - grammar.lex_param = code.token_code.s_value - when T::P_parse_param - ts.next - code = ts.consume!(T::User_code) - code = grammar.build_code(:parse_param, code) - grammar.parse_param = code.token_code.s_value - when T::P_initial_action - ts.next - code = ts.consume!(T::User_code) - code = grammar.build_code(:initial_action, code) - ts.consume(T::Semicolon) - grammar.initial_action = code - when T::P_union - lineno = ts.current_token.line - ts.next - code = ts.consume!(T::User_code) - code = grammar.build_code(:union, code) - ts.consume(T::Semicolon) - grammar.set_union(code, lineno) - when T::P_token - # %token tag? (ident number? string?)+ - # - # * ident can be char, e.g. '\\', '\t', '\13' - # * number is a token_id for term - # - # These are valid token declaration (from CRuby parse.y) - # - # %token END_OF_INPUT 0 "end-of-input" - # %token '\\' "backslash" - # %token tSP "escaped space" - # %token tUPLUS 132 "unary+" - # %token tCOLON3 ":: at EXPR_BEG" - # %token tSTRING_DBEG tSTRING_DVAR tLAMBEG tLABEL_END - # - # - # See: https://www.gnu.org/software/bison/manual/html_node/Symbol-Decls.html - ts.next - opt_tag = ts.consume(T::Tag) - - while (id = ts.consume(T::Ident, T::Char)) do - opt_number = ts.consume(T::Number) - opt_string = ts.consume(T::String) - # Can replace 0 (EOF) - grammar.add_term( - id: id, - alias_name: opt_string && opt_string.s_value, - token_id: opt_number && opt_number.s_value, - tag: opt_tag, - replace: true, - ) + def _racc_do_parse_rb(arg, in_debug) + action_table, action_check, action_default, action_pointer, + _, _, _, _, + _, _, token_table, * = arg + + _racc_init_sysvars + tok = act = i = nil + + catch(:racc_end_parse) { + while true + if i = action_pointer[@racc_state[-1]] + if @racc_read_next + if @racc_t != 0 # not EOF + tok, @racc_val = next_token() + unless tok # EOF + @racc_t = 0 + else + @racc_t = (token_table[tok] or 1) # error token + end + racc_read_token(@racc_t, tok, @racc_val) if @yydebug + @racc_read_next = false + end + end + i += @racc_t + unless i >= 0 and + act = action_table[i] and + action_check[i] == @racc_state[-1] + act = action_default[@racc_state[-1]] + end + else + act = action_default[@racc_state[-1]] end - when T::P_type - # %type tag? (ident|char|string)+ - # - # See: https://www.gnu.org/software/bison/manual/html_node/Symbol-Decls.html - ts.next - opt_tag = ts.consume(T::Tag) - - while (id = ts.consume(T::Ident, T::Char, T::String)) do - grammar.add_type( - id: id, - tag: opt_tag - ) + while act = _racc_evalact(act, arg) + ; end - when T::P_nonassoc - # %nonassoc (ident|char|string)+ - ts.next - while (id = ts.consume(T::Ident, T::Char, T::String)) do - sym = grammar.add_term(id: id) - grammar.add_nonassoc(sym, precedence_number) + end + } + end + + # Another entry point for the parser. + # If you use this method, you must implement RECEIVER#METHOD_ID method. + # + # RECEIVER#METHOD_ID is a method to get next token. + # It must 'yield' the token, which format is [TOKEN-SYMBOL, VALUE]. + class_eval <<~RUBY, __FILE__, __LINE__ + 1 + def yyparse(recv, mid) + #{Racc_YY_Parse_Method}(recv, mid, _racc_setup(), false) + end + RUBY + + def _racc_yyparse_rb(recv, mid, arg, c_debug) + action_table, action_check, action_default, action_pointer, + _, _, _, _, + _, _, token_table, * = arg + + _racc_init_sysvars + + catch(:racc_end_parse) { + until i = action_pointer[@racc_state[-1]] + while act = _racc_evalact(action_default[@racc_state[-1]], arg) + ; end - precedence_number += 1 - when T::P_left - # %left (ident|char|string)+ - ts.next - while (id = ts.consume(T::Ident, T::Char, T::String)) do - sym = grammar.add_term(id: id) - grammar.add_left(sym, precedence_number) + end + recv.__send__(mid) do |tok, val| + unless tok + @racc_t = 0 + else + @racc_t = (token_table[tok] or 1) # error token end - precedence_number += 1 - when T::P_right - # %right (ident|char|string)+ - ts.next - while (id = ts.consume(T::Ident, T::Char, T::String)) do - sym = grammar.add_term(id: id) - grammar.add_right(sym, precedence_number) + @racc_val = val + @racc_read_next = false + + i += @racc_t + unless i >= 0 and + act = action_table[i] and + action_check[i] == @racc_state[-1] + act = action_default[@racc_state[-1]] end - precedence_number += 1 - when T::P_precedence - # %precedence (ident|char|string)+ - ts.next - while (id = ts.consume(T::Ident, T::Char, T::String)) do - sym = grammar.add_term(id: id) - grammar.add_precedence(sym, precedence_number) + while act = _racc_evalact(act, arg) + ; + end + + while !(i = action_pointer[@racc_state[-1]]) || + ! @racc_read_next || + @racc_t == 0 # $ + unless i and i += @racc_t and + i >= 0 and + act = action_table[i] and + action_check[i] == @racc_state[-1] + act = action_default[@racc_state[-1]] + end + while act = _racc_evalact(act, arg) + ; + end end - precedence_number += 1 - when nil - # end of input - raise "Reach to end of input within declarations" - else - raise "Unexpected token: #{ts.current_token}" end - end + } end - def parse_grammar_rules(ts, grammar) - while !ts.eots? do - parse_grammar_rule(ts, grammar) + ### + ### common + ### + + def _racc_evalact(act, arg) + action_table, action_check, _, action_pointer, + _, _, _, _, + _, _, _, shift_n, + reduce_n, * = arg + nerr = 0 # tmp + + if act > 0 and act < shift_n + # + # shift + # + if @racc_error_status > 0 + @racc_error_status -= 1 unless @racc_t <= 1 # error token or EOF + end + @racc_vstack.push @racc_val + @racc_state.push act + @racc_read_next = true + if @yydebug + @racc_tstack.push @racc_t + racc_shift @racc_t, @racc_tstack, @racc_vstack + end + + elsif act < 0 and act > -reduce_n + # + # reduce + # + code = catch(:racc_jump) { + @racc_state.push _racc_do_reduce(arg, act) + false + } + if code + case code + when 1 # yyerror + @racc_user_yyerror = true # user_yyerror + return -reduce_n + when 2 # yyaccept + return shift_n + else + raise '[Racc Bug] unknown jump code' + end + end + + elsif act == shift_n + # + # accept + # + racc_accept if @yydebug + throw :racc_end_parse, @racc_vstack[0] + + elsif act == -reduce_n + # + # error + # + case @racc_error_status + when 0 + unless arg[21] # user_yyerror + nerr += 1 + on_error @racc_t, @racc_val, @racc_vstack + end + when 3 + if @racc_t == 0 # is $ + # We're at EOF, and another error occurred immediately after + # attempting auto-recovery + throw :racc_end_parse, nil + end + @racc_read_next = true + end + @racc_user_yyerror = false + @racc_error_status = 3 + while true + if i = action_pointer[@racc_state[-1]] + i += 1 # error token + if i >= 0 and + (act = action_table[i]) and + action_check[i] == @racc_state[-1] + break + end + end + throw :racc_end_parse, nil if @racc_state.size <= 1 + @racc_state.pop + @racc_vstack.pop + if @yydebug + @racc_tstack.pop + racc_e_pop @racc_state, @racc_tstack, @racc_vstack + end + end + return act + + else + raise "[Racc Bug] unknown action #{act.inspect}" end + + racc_next_state(@racc_state[-1], @racc_state) if @yydebug + + nil end - # TODO: Take care of %prec of rule. - # If %prec exists, user code before %prec - # is NOT an action. For example "{ code 3 }" is NOT an action. - # - # keyword_class { code 2 } tSTRING '!' keyword_end { code 3 } %prec "=" - def parse_grammar_rule(ts, grammar) - # LHS - lhs = ts.consume!(T::Ident_Colon) # class: - lhs.type = T::Ident - if named_ref = ts.consume(T::Named_Ref) - lhs.alias = named_ref.s_value + def _racc_do_reduce(arg, act) + _, _, _, _, + goto_table, goto_check, goto_default, goto_pointer, + nt_base, reduce_table, _, _, + _, use_result, * = arg + + state = @racc_state + vstack = @racc_vstack + tstack = @racc_tstack + + i = act * -3 + len = reduce_table[i] + reduce_to = reduce_table[i+1] + method_id = reduce_table[i+2] + void_array = [] + + tmp_t = tstack[-len, len] if @yydebug + tmp_v = vstack[-len, len] + tstack[-len, len] = void_array if @yydebug + vstack[-len, len] = void_array + state[-len, len] = void_array + + # tstack must be updated AFTER method call + if use_result + vstack.push __send__(method_id, tmp_v, vstack, tmp_v[0]) + else + vstack.push __send__(method_id, tmp_v, vstack) end + tstack.push reduce_to - rhs = parse_grammar_rule_rhs(ts, grammar, lhs) - - grammar.add_rule(lhs: lhs, rhs: rhs, lineno: rhs.first ? rhs.first.line : lhs.line) - - while true do - case ts.current_type - when T::Bar - # | - bar_lineno = ts.current_token.line - ts.next - rhs = parse_grammar_rule_rhs(ts, grammar, lhs) - grammar.add_rule(lhs: lhs, rhs: rhs, lineno: rhs.first ? rhs.first.line : bar_lineno) - when T::Semicolon - # ; - ts.next - break - when T::Ident_Colon - # Next lhs can be here because ";" is optional. - # Do not consume next token. - break - when nil - # end of input can be here when ";" is omitted - break - else - raise "Unexpected token: #{ts.current_token}" + racc_reduce(tmp_t, reduce_to, tstack, vstack) if @yydebug + + k1 = reduce_to - nt_base + if i = goto_pointer[k1] + i += state[-1] + if i >= 0 and (curstate = goto_table[i]) and goto_check[i] == k1 + return curstate end end + goto_default[k1] end - def parse_grammar_rule_rhs(ts, grammar, lhs) - a = [] - prec_seen = false - code_after_prec = false - - while true do - # TODO: String can be here - case ts.current_type - when T::Ident - # keyword_class - - raise "Ident after %prec" if prec_seen - a << ts.current_token - ts.next - when T::Char - # '!' - - raise "Char after %prec" if prec_seen - a << ts.current_token - ts.next - when T::P_prec - # %prec tPLUS - # - # See: https://www.gnu.org/software/bison/manual/html_node/Contextual-Precedence.html - - ts.next - prec_seen = true - precedence_id = ts.consume!(T::Ident, T::String, T::Char) - precedence_sym = grammar.find_symbol_by_id!(precedence_id) - a << precedence_sym - when T::User_code - # { code } in the middle of rhs - - if prec_seen - raise "Multiple User_code after %prec" if code_after_prec - code_after_prec = true - end + # This method is called when a parse error is found. + # + # ERROR_TOKEN_ID is an internal ID of token which caused error. + # You can get string representation of this ID by calling + # #token_to_str. + # + # ERROR_VALUE is a value of error token. + # + # value_stack is a stack of symbol values. + # DO NOT MODIFY this object. + # + # This method raises ParseError by default. + # + # If this method returns, parsers enter "error recovering mode". + def on_error(t, val, vstack) + raise ParseError, sprintf("\nparse error on value %s (%s)", + val.inspect, token_to_str(t) || '?') + end - code = ts.current_token - code.numberize_references(lhs, a) - grammar.build_references(code) - a << code - ts.next - when T::Named_Ref - ts.previous_token.alias = ts.current_token.s_value - ts.next - when T::Bar - # | - break - when T::Semicolon - # ; - break - when T::Ident_Colon - # Next lhs can be here because ";" is optional. - break - when nil - # end of input can be here when ";" is omitted - break - else - raise "Unexpected token: #{ts.current_token}" - end + # Enter error recovering mode. + # This method does not call #on_error. + def yyerror + throw :racc_jump, 1 + end + + # Exit parser. + # Return value is +Symbol_Value_Stack[0]+. + def yyaccept + throw :racc_jump, 2 + end + + # Leave error recovering mode. + def yyerrok + @racc_error_status = 0 + end + + # For debugging output + def racc_read_token(t, tok, val) + @racc_debug_out.print 'read ' + @racc_debug_out.print tok.inspect, '(', racc_token2str(t), ') ' + @racc_debug_out.puts val.inspect + @racc_debug_out.puts + end + + def racc_shift(tok, tstack, vstack) + @racc_debug_out.puts "shift #{racc_token2str tok}" + racc_print_stacks tstack, vstack + @racc_debug_out.puts + end + + def racc_reduce(toks, sim, tstack, vstack) + out = @racc_debug_out + out.print 'reduce ' + if toks.empty? + out.print ' ' + else + toks.each {|t| out.print ' ', racc_token2str(t) } + end + out.puts " --> #{racc_token2str(sim)}" + racc_print_stacks tstack, vstack + @racc_debug_out.puts + end + + def racc_accept + @racc_debug_out.puts 'accept' + @racc_debug_out.puts + end + + def racc_e_pop(state, tstack, vstack) + @racc_debug_out.puts 'error recovering mode: pop token' + racc_print_states state + racc_print_stacks tstack, vstack + @racc_debug_out.puts + end + + def racc_next_state(curstate, state) + @racc_debug_out.puts "goto #{curstate}" + racc_print_states state + @racc_debug_out.puts + end + + def racc_print_stacks(t, v) + out = @racc_debug_out + out.print ' [' + t.each_index do |i| + out.print ' (', racc_token2str(t[i]), ' ', v[i].inspect, ')' end + out.puts ' ]' + end + + def racc_print_states(s) + out = @racc_debug_out + out.print ' [' + s.each {|st| out.print ' ', st } + out.puts ' ]' + end - return a + def racc_token2str(tok) + self.class::Racc_token_to_s_table[tok] or + raise "[Racc Bug] can't convert token #{tok} to string" end + + # Convert internal ID of token symbol to the string. + def token_to_str(t) + self.class::Racc_token_to_s_table[t] + end + + end + +end + +...end racc/parser.rb/module_eval... +end +###### racc/parser.rb end +module Lrama + class Parser < Racc::Parser + +module_eval(<<'...end parser.y/module_eval...', 'parser.y', 387) + +include Lrama::Report::Duration + +def initialize(text) + @text = text +end + +def parse + report_duration(:parse) do + @lexer = Lrama::Lexer.new(@text) + @grammar = Lrama::Grammar.new + @precedence_number = 0 + do_parse + @grammar.extract_references + @grammar.prepare + @grammar.compute_nullable + @grammar.compute_first_set + @grammar.validate! + @grammar + end +end + +def next_token + @lexer.next_token +end + +def on_error(error_token_id, error_value, value_stack) + raise ParseError, sprintf("\n%d:%d: parse error on value %s (%s)", + @lexer.line, @lexer.column, error_value.inspect, token_to_str(error_token_id) || '?') +end +...end parser.y/module_eval... +##### State transition tables begin ### + +racc_action_table = [ + 77, 6, 41, 42, 7, 83, 65, 56, 41, 42, + 68, 41, 42, 3, 134, 8, 20, 22, 23, 24, + 25, 26, 27, 28, 29, 30, 65, 82, 41, 42, + 65, 132, 135, 32, 38, 84, 41, 42, 134, 68, + 41, 42, 65, 68, 41, 42, 131, 61, 41, 42, + 39, 9, 41, 42, 44, 14, 135, 12, 65, 13, + 15, 16, 17, 18, 41, 42, 19, 20, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 65, 46, 65, + 41, 42, 65, 46, 65, 41, 42, 65, 41, 42, + 65, 41, 42, 65, 41, 42, 65, 41, 42, 41, + 42, 41, 42, 65, 41, 42, 41, 42, 153, 41, + 42, 153, 41, 42, 153, 41, 42, 153, 41, 42, + 65, 68, 41, 42, 153, 41, 42, 20, 22, 23, + 24, 25, 26, 27, 28, 29, 30, 41, 42, 41, + 42, 153, 41, 42, 46, 38, 41, 42, 41, 42, + 41, 42, 41, 42, 41, 42, 49, 50, 51, 52, + 53, 74, 78, 80, 85, 85, 85, 92, 96, 97, + 105, 106, 108, 109, 110, 111, 112, 113, 116, 118, + 119, 122, 123, 124, 138, 139, 140, 141, 142, 143, + 122, 80, 148, 149, 156, 160, 161, 80, 80 ] + +racc_action_check = [ + 33, 2, 13, 13, 2, 40, 121, 25, 25, 25, + 27, 27, 27, 1, 121, 3, 33, 33, 33, 33, + 33, 33, 33, 33, 33, 33, 26, 40, 121, 121, + 144, 120, 121, 7, 33, 40, 55, 55, 144, 28, + 28, 28, 60, 29, 29, 29, 120, 26, 26, 26, + 12, 4, 144, 144, 14, 4, 144, 4, 61, 4, + 4, 4, 4, 4, 60, 60, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 97, 15, 99, + 61, 61, 117, 16, 135, 56, 56, 141, 66, 66, + 142, 67, 67, 143, 68, 68, 150, 71, 71, 97, + 97, 99, 99, 154, 117, 117, 135, 135, 141, 141, + 141, 142, 142, 142, 143, 143, 143, 150, 150, 150, + 155, 30, 30, 30, 154, 154, 154, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 72, 72, 73, + 73, 155, 155, 155, 17, 9, 92, 92, 94, 94, + 100, 100, 102, 102, 114, 114, 18, 20, 22, 23, + 24, 31, 36, 37, 45, 47, 48, 54, 58, 59, + 79, 80, 86, 87, 88, 89, 90, 91, 95, 103, + 104, 105, 106, 107, 125, 126, 127, 128, 129, 130, + 131, 133, 136, 137, 146, 157, 159, 160, 161 ] + +racc_action_pointer = [ + nil, 13, -2, 15, 49, nil, nil, 26, nil, 109, + nil, nil, 41, -27, 47, 63, 68, 129, 141, nil, + 142, nil, 143, 144, 145, -21, 19, -18, 11, 15, + 93, 157, nil, -2, nil, nil, 145, 129, nil, nil, + -2, nil, nil, nil, nil, 149, nil, 150, 151, nil, + nil, nil, nil, nil, 139, 7, 56, nil, 159, 141, + 35, 51, nil, nil, nil, nil, 59, 62, 65, nil, + nil, 68, 108, 110, nil, nil, nil, nil, nil, 139, + 142, nil, nil, nil, nil, nil, 168, 169, 170, 171, + 172, 173, 117, nil, 119, 171, nil, 70, nil, 72, + 121, nil, 123, 174, 176, 166, 147, 179, nil, nil, + nil, nil, nil, nil, 125, nil, nil, 75, nil, nil, + 14, -1, nil, nil, nil, 168, 169, 170, 171, 172, + 173, 175, nil, 157, nil, 77, 188, 177, nil, nil, + nil, 80, 83, 86, 23, nil, 190, nil, nil, nil, + 89, nil, nil, nil, 96, 113, nil, 179, nil, 180, + 163, 164, nil, nil ] + +racc_action_default = [ + -2, -104, -8, -104, -104, -3, -4, -104, 164, -104, + -9, -10, -104, -104, -104, -104, -104, -104, -104, -20, + -104, -24, -104, -104, -104, -104, -104, -104, -104, -104, + -104, -104, -7, -91, -71, -73, -104, -88, -90, -11, + -95, -69, -70, -94, -13, -14, -60, -15, -16, -17, + -21, -25, -28, -31, -34, -40, -104, -43, -46, -35, + -50, -104, -53, -55, -56, -103, -36, -63, -104, -66, + -68, -37, -38, -39, -5, -1, -72, -92, -74, -104, + -104, -12, -96, -97, -98, -57, -104, -104, -104, -104, + -104, -104, -104, -44, -41, -48, -47, -104, -54, -51, + -65, -67, -64, -104, -104, -79, -104, -104, -61, -18, + -22, -26, -29, -32, -42, -45, -49, -52, -6, -93, + -75, -76, -84, -89, -58, -104, -104, -104, -104, -104, + -104, -79, -78, -88, -81, -104, -104, -104, -62, -19, + -23, -104, -104, -104, -77, -80, -104, -87, -85, -59, + -27, -99, -101, -102, -30, -33, -82, -104, -100, -104, + -88, -88, -86, -83 ] + +racc_goto_table = [ + 79, 43, 62, 60, 55, 121, 93, 101, 34, 66, + 71, 72, 73, 58, 1, 70, 70, 70, 70, 100, + 2, 102, 4, 158, 100, 100, 100, 158, 158, 33, + 75, 144, 76, 5, 31, 94, 98, 62, 99, 103, + 101, 10, 101, 58, 58, 93, 45, 47, 48, 150, + 154, 155, 11, 40, 70, 70, 70, 81, 87, 70, + 70, 70, 126, 88, 127, 93, 89, 128, 90, 129, + 91, 114, 130, 62, 117, 98, 54, 59, 95, 115, + 58, 107, 58, 137, 86, 125, 120, 146, 70, 159, + 70, 136, 157, 98, 104, nil, 145, 133, nil, nil, + nil, nil, 58, nil, nil, nil, nil, nil, nil, nil, + nil, 147, nil, nil, nil, nil, nil, nil, nil, nil, + 133, nil, nil, 162, 163 ] + +racc_goto_check = [ + 46, 31, 35, 34, 29, 48, 30, 42, 43, 28, + 28, 28, 28, 31, 1, 31, 31, 31, 31, 41, + 2, 41, 3, 54, 41, 41, 41, 54, 54, 4, + 5, 48, 43, 6, 7, 29, 35, 35, 34, 8, + 42, 9, 42, 31, 31, 30, 13, 13, 13, 17, + 17, 17, 10, 11, 31, 31, 31, 12, 14, 31, + 31, 31, 15, 18, 19, 30, 20, 21, 22, 23, + 24, 29, 25, 35, 34, 35, 26, 27, 32, 33, + 31, 37, 31, 38, 39, 40, 47, 49, 31, 50, + 31, 51, 52, 35, 53, nil, 46, 35, nil, nil, + nil, nil, 31, nil, nil, nil, nil, nil, nil, nil, + nil, 35, nil, nil, nil, nil, nil, nil, nil, nil, + 35, nil, nil, 46, 46 ] + +racc_goto_pointer = [ + nil, 14, 20, 20, 20, -3, 31, 28, -35, 37, + 48, 40, 17, 31, 9, -47, nil, -92, 13, -46, + 15, -44, 16, -43, 17, -41, 51, 51, -18, -21, + -49, -12, 20, -16, -23, -24, nil, -4, -41, 38, + -23, -47, -60, -1, nil, nil, -37, -19, -100, -47, + -67, -31, -56, 17, -127 ] + +racc_goto_default = [ + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + 36, nil, nil, nil, nil, nil, 21, nil, nil, nil, + nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, + 57, 63, nil, nil, nil, 152, 64, nil, nil, nil, + nil, 67, 69, nil, 35, 37, nil, nil, nil, nil, + nil, nil, nil, nil, 151 ] + +racc_reduce_table = [ + 0, 0, :racc_error, + 5, 39, :_reduce_none, + 0, 40, :_reduce_none, + 2, 40, :_reduce_none, + 0, 45, :_reduce_4, + 0, 46, :_reduce_5, + 5, 44, :_reduce_6, + 2, 44, :_reduce_none, + 0, 41, :_reduce_8, + 2, 41, :_reduce_none, + 1, 47, :_reduce_none, + 2, 47, :_reduce_11, + 3, 47, :_reduce_none, + 2, 47, :_reduce_none, + 2, 47, :_reduce_none, + 2, 47, :_reduce_15, + 2, 47, :_reduce_16, + 0, 52, :_reduce_17, + 0, 53, :_reduce_18, + 6, 47, :_reduce_19, + 1, 47, :_reduce_none, + 0, 56, :_reduce_21, + 0, 57, :_reduce_22, + 6, 48, :_reduce_23, + 1, 48, :_reduce_none, + 0, 58, :_reduce_25, + 0, 59, :_reduce_26, + 7, 48, :_reduce_none, + 0, 60, :_reduce_28, + 0, 61, :_reduce_29, + 7, 48, :_reduce_30, + 0, 62, :_reduce_31, + 0, 63, :_reduce_32, + 7, 48, :_reduce_33, + 2, 54, :_reduce_none, + 2, 54, :_reduce_35, + 2, 54, :_reduce_36, + 2, 54, :_reduce_37, + 2, 54, :_reduce_38, + 2, 54, :_reduce_39, + 1, 64, :_reduce_40, + 2, 64, :_reduce_41, + 3, 64, :_reduce_42, + 1, 67, :_reduce_43, + 2, 67, :_reduce_44, + 3, 68, :_reduce_45, + 0, 70, :_reduce_none, + 1, 70, :_reduce_none, + 0, 71, :_reduce_none, + 1, 71, :_reduce_none, + 1, 65, :_reduce_50, + 2, 65, :_reduce_51, + 3, 65, :_reduce_52, + 1, 72, :_reduce_53, + 2, 72, :_reduce_54, + 1, 73, :_reduce_none, + 1, 73, :_reduce_none, + 0, 75, :_reduce_57, + 0, 76, :_reduce_58, + 6, 51, :_reduce_59, + 0, 77, :_reduce_60, + 0, 78, :_reduce_61, + 5, 51, :_reduce_62, + 1, 66, :_reduce_63, + 2, 66, :_reduce_64, + 2, 66, :_reduce_65, + 1, 79, :_reduce_66, + 2, 79, :_reduce_67, + 1, 80, :_reduce_none, + 1, 69, :_reduce_69, + 1, 69, :_reduce_70, + 1, 42, :_reduce_none, + 2, 42, :_reduce_none, + 1, 81, :_reduce_none, + 2, 81, :_reduce_none, + 4, 82, :_reduce_75, + 1, 85, :_reduce_76, + 3, 85, :_reduce_77, + 2, 85, :_reduce_none, + 0, 86, :_reduce_79, + 3, 86, :_reduce_80, + 0, 87, :_reduce_81, + 0, 88, :_reduce_82, + 7, 86, :_reduce_83, + 0, 89, :_reduce_84, + 0, 90, :_reduce_85, + 6, 86, :_reduce_86, + 3, 86, :_reduce_87, + 0, 84, :_reduce_none, + 3, 84, :_reduce_89, + 1, 83, :_reduce_none, + 0, 43, :_reduce_none, + 0, 91, :_reduce_92, + 3, 43, :_reduce_93, + 1, 49, :_reduce_none, + 0, 50, :_reduce_none, + 1, 50, :_reduce_none, + 1, 50, :_reduce_none, + 1, 50, :_reduce_none, + 1, 55, :_reduce_99, + 2, 55, :_reduce_100, + 1, 92, :_reduce_none, + 1, 92, :_reduce_none, + 1, 74, :_reduce_103 ] + +racc_reduce_n = 104 + +racc_shift_n = 164 + +racc_token_table = { + false => 0, + :error => 1, + "%%" => 2, + "%{" => 3, + :C_DECLARATION => 4, + "%}" => 5, + "%require" => 6, + :STRING => 7, + "%expect" => 8, + :INTEGER => 9, + "%define" => 10, + "%param" => 11, + "%lex-param" => 12, + "%parse-param" => 13, + "%initial-action" => 14, + "{" => 15, + "}" => 16, + ";" => 17, + "%union" => 18, + "%destructor" => 19, + "%printer" => 20, + "%error-token" => 21, + "%token" => 22, + "%type" => 23, + "%left" => 24, + "%right" => 25, + "%precedence" => 26, + "%nonassoc" => 27, + :TAG => 28, + :IDENTIFIER => 29, + :CHARACTER => 30, + ":" => 31, + "|" => 32, + "%prec" => 33, + "[" => 34, + "]" => 35, + :IDENT_COLON => 36, + "{...}" => 37 } + +racc_nt_base = 38 + +racc_use_result_var = true + +Racc_arg = [ + racc_action_table, + racc_action_check, + racc_action_default, + racc_action_pointer, + racc_goto_table, + racc_goto_check, + racc_goto_default, + racc_goto_pointer, + racc_nt_base, + racc_reduce_table, + racc_token_table, + racc_shift_n, + racc_reduce_n, + racc_use_result_var ] +Ractor.make_shareable(Racc_arg) if defined?(Ractor) + +Racc_token_to_s_table = [ + "$end", + "error", + "\"%%\"", + "\"%{\"", + "C_DECLARATION", + "\"%}\"", + "\"%require\"", + "STRING", + "\"%expect\"", + "INTEGER", + "\"%define\"", + "\"%param\"", + "\"%lex-param\"", + "\"%parse-param\"", + "\"%initial-action\"", + "\"{\"", + "\"}\"", + "\";\"", + "\"%union\"", + "\"%destructor\"", + "\"%printer\"", + "\"%error-token\"", + "\"%token\"", + "\"%type\"", + "\"%left\"", + "\"%right\"", + "\"%precedence\"", + "\"%nonassoc\"", + "TAG", + "IDENTIFIER", + "CHARACTER", + "\":\"", + "\"|\"", + "\"%prec\"", + "\"[\"", + "\"]\"", + "IDENT_COLON", + "\"{...}\"", + "$start", + "input", + "prologue_declarations", + "bison_declarations", + "grammar", + "epilogue_opt", + "prologue_declaration", + "@1", + "@2", + "bison_declaration", + "grammar_declaration", + "variable", + "value", + "params", + "@3", + "@4", + "symbol_declaration", + "generic_symlist", + "@5", + "@6", + "@7", + "@8", + "@9", + "@10", + "@11", + "@12", + "token_declarations", + "symbol_declarations", + "token_declarations_for_precedence", + "token_declaration_list", + "token_declaration", + "id", + "int_opt", + "alias", + "symbol_declaration_list", + "symbol", + "string_as_id", + "@13", + "@14", + "@15", + "@16", + "token_declaration_list_for_precedence", + "token_declaration_for_precedence", + "rules_or_grammar_declaration", + "rules", + "id_colon", + "named_ref_opt", + "rhs_list", + "rhs", + "@17", + "@18", + "@19", + "@20", + "@21", + "generic_symlist_item" ] +Ractor.make_shareable(Racc_token_to_s_table) if defined?(Ractor) + +Racc_debug_parser = false + +##### State transition tables end ##### + +# reduce 0 omitted + +# reduce 1 omitted + +# reduce 2 omitted + +# reduce 3 omitted + +module_eval(<<'.,.,', 'parser.y', 9) + def _reduce_4(val, _values, result) + @lexer.status = :c_declaration + @lexer.end_symbol = '%}' + @grammar.prologue_first_lineno = @lexer.line + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 15) + def _reduce_5(val, _values, result) + @lexer.status = :initial + @lexer.end_symbol = nil + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 20) + def _reduce_6(val, _values, result) + @grammar.prologue = val[2].s_value + + result + end +.,., + +# reduce 7 omitted + +module_eval(<<'.,.,', 'parser.y', 24) + def _reduce_8(val, _values, result) + result = "" + result + end +.,., + +# reduce 9 omitted + +# reduce 10 omitted + +module_eval(<<'.,.,', 'parser.y', 28) + def _reduce_11(val, _values, result) + @grammar.expect = val[1] + result + end +.,., + +# reduce 12 omitted + +# reduce 13 omitted + +# reduce 14 omitted + +module_eval(<<'.,.,', 'parser.y', 34) + def _reduce_15(val, _values, result) + val[1].each {|token| + token.references = [] + @grammar.lex_param = @grammar.build_code(:lex_param, token).token_code.s_value + } + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 41) + def _reduce_16(val, _values, result) + val[1].each {|token| + token.references = [] + @grammar.parse_param = @grammar.build_code(:parse_param, token).token_code.s_value + } + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 48) + def _reduce_17(val, _values, result) + @lexer.status = :c_declaration + @lexer.end_symbol = '}' + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 53) + def _reduce_18(val, _values, result) + @lexer.status = :initial + @lexer.end_symbol = nil + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 58) + def _reduce_19(val, _values, result) + @grammar.initial_action = @grammar.build_code(:initial_action, val[3]) + + result + end +.,., + +# reduce 20 omitted + +module_eval(<<'.,.,', 'parser.y', 64) + def _reduce_21(val, _values, result) + @lexer.status = :c_declaration + @lexer.end_symbol = '}' + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 69) + def _reduce_22(val, _values, result) + @lexer.status = :initial + @lexer.end_symbol = nil + + result end +.,., + +module_eval(<<'.,.,', 'parser.y', 74) + def _reduce_23(val, _values, result) + @grammar.set_union(@grammar.build_code(:union, val[3]), val[3].line) + + result + end +.,., + +# reduce 24 omitted + +module_eval(<<'.,.,', 'parser.y', 79) + def _reduce_25(val, _values, result) + @lexer.status = :c_declaration + @lexer.end_symbol = '}' + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 84) + def _reduce_26(val, _values, result) + @lexer.status = :initial + @lexer.end_symbol = nil + + result + end +.,., + +# reduce 27 omitted + +module_eval(<<'.,.,', 'parser.y', 90) + def _reduce_28(val, _values, result) + @lexer.status = :c_declaration + @lexer.end_symbol = '}' + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 95) + def _reduce_29(val, _values, result) + @lexer.status = :initial + @lexer.end_symbol = nil + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 100) + def _reduce_30(val, _values, result) + @grammar.add_printer(ident_or_tags: val[6], code: @grammar.build_code(:printer, val[3]), lineno: val[3].line) + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 104) + def _reduce_31(val, _values, result) + @lexer.status = :c_declaration + @lexer.end_symbol = '}' + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 109) + def _reduce_32(val, _values, result) + @lexer.status = :initial + @lexer.end_symbol = nil + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 114) + def _reduce_33(val, _values, result) + @grammar.add_error_token(ident_or_tags: val[6], code: @grammar.build_code(:error_token, val[3]), lineno: val[3].line) + + result + end +.,., + +# reduce 34 omitted + +module_eval(<<'.,.,', 'parser.y', 120) + def _reduce_35(val, _values, result) + val[1].each {|hash| + hash[:tokens].each {|id| + @grammar.add_type(id: id, tag: hash[:tag]) + } + } + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 128) + def _reduce_36(val, _values, result) + val[1].each {|hash| + hash[:tokens].each {|id| + sym = @grammar.add_term(id: id) + @grammar.add_left(sym, @precedence_number) + } + } + @precedence_number += 1 + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 138) + def _reduce_37(val, _values, result) + val[1].each {|hash| + hash[:tokens].each {|id| + sym = @grammar.add_term(id: id) + @grammar.add_right(sym, @precedence_number) + } + } + @precedence_number += 1 + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 148) + def _reduce_38(val, _values, result) + val[1].each {|hash| + hash[:tokens].each {|id| + sym = @grammar.add_term(id: id) + @grammar.add_precedence(sym, @precedence_number) + } + } + @precedence_number += 1 + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 158) + def _reduce_39(val, _values, result) + val[1].each {|hash| + hash[:tokens].each {|id| + sym = @grammar.add_term(id: id) + @grammar.add_nonassoc(sym, @precedence_number) + } + } + @precedence_number += 1 + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 169) + def _reduce_40(val, _values, result) + val[0].each {|token_declaration| + @grammar.add_term(id: token_declaration[0], alias_name: token_declaration[2], token_id: token_declaration[1], tag: nil, replace: true) + } + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 175) + def _reduce_41(val, _values, result) + val[1].each {|token_declaration| + @grammar.add_term(id: token_declaration[0], alias_name: token_declaration[2], token_id: token_declaration[1], tag: val[0], replace: true) + } + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 181) + def _reduce_42(val, _values, result) + val[2].each {|token_declaration| + @grammar.add_term(id: token_declaration[0], alias_name: token_declaration[2], token_id: token_declaration[1], tag: val[1], replace: true) + } + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 186) + def _reduce_43(val, _values, result) + result = [val[0]] + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 187) + def _reduce_44(val, _values, result) + result = val[0].append(val[1]) + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 189) + def _reduce_45(val, _values, result) + result = val + result + end +.,., + +# reduce 46 omitted + +# reduce 47 omitted + +# reduce 48 omitted + +# reduce 49 omitted + +module_eval(<<'.,.,', 'parser.y', 199) + def _reduce_50(val, _values, result) + result = [{tag: nil, tokens: val[0]}] + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 203) + def _reduce_51(val, _values, result) + result = [{tag: val[0], tokens: val[1]}] + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 207) + def _reduce_52(val, _values, result) + result = val[0].append({tag: val[1], tokens: val[2]}) + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 210) + def _reduce_53(val, _values, result) + result = [val[0]] + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 211) + def _reduce_54(val, _values, result) + result = val[0].append(val[1]) + result + end +.,., + +# reduce 55 omitted + +# reduce 56 omitted + +module_eval(<<'.,.,', 'parser.y', 218) + def _reduce_57(val, _values, result) + @lexer.status = :c_declaration + @lexer.end_symbol = '}' + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 223) + def _reduce_58(val, _values, result) + @lexer.status = :initial + @lexer.end_symbol = nil + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 228) + def _reduce_59(val, _values, result) + result = val[0].append(val[3]) + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 232) + def _reduce_60(val, _values, result) + @lexer.status = :c_declaration + @lexer.end_symbol = '}' + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 237) + def _reduce_61(val, _values, result) + @lexer.status = :initial + @lexer.end_symbol = nil + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 242) + def _reduce_62(val, _values, result) + result = [val[2]] + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 247) + def _reduce_63(val, _values, result) + result = [{tag: nil, tokens: val[0]}] + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 251) + def _reduce_64(val, _values, result) + result = [{tag: val[0], tokens: val[1]}] + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 255) + def _reduce_65(val, _values, result) + result = val[0].append({tag: nil, tokens: val[1]}) + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 258) + def _reduce_66(val, _values, result) + result = [val[0]] + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 259) + def _reduce_67(val, _values, result) + result = val[0].append(val[1]) + result + end +.,., + +# reduce 68 omitted + +module_eval(<<'.,.,', 'parser.y', 263) + def _reduce_69(val, _values, result) + raise "Ident after %prec" if @prec_seen + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 264) + def _reduce_70(val, _values, result) + raise "Char after %prec" if @prec_seen + result + end +.,., + +# reduce 71 omitted + +# reduce 72 omitted + +# reduce 73 omitted + +# reduce 74 omitted + +module_eval(<<'.,.,', 'parser.y', 274) + def _reduce_75(val, _values, result) + lhs = val[0] + lhs.alias = val[1] + val[3].each {|hash| + @grammar.add_rule(lhs: lhs, rhs: hash[:rhs], lineno: hash[:lineno]) + } + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 283) + def _reduce_76(val, _values, result) + result = [{rhs: val[0], lineno: val[0].first&.line || @lexer.line - 1}] + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 287) + def _reduce_77(val, _values, result) + result = val[0].append({rhs: val[2], lineno: val[2].first&.line || @lexer.line - 1}) + + result + end +.,., + +# reduce 78 omitted + +module_eval(<<'.,.,', 'parser.y', 293) + def _reduce_79(val, _values, result) + result = [] + @prec_seen = false + @code_after_prec = false + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 299) + def _reduce_80(val, _values, result) + token = val[1] + val[1].alias = val[2] + result = val[0].append(token) + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 305) + def _reduce_81(val, _values, result) + if @prec_seen + raise "Multiple User_code after %prec" if @code_after_prec + @code_after_prec = true + end + @lexer.status = :c_declaration + @lexer.end_symbol = '}' + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 314) + def _reduce_82(val, _values, result) + @lexer.status = :initial + @lexer.end_symbol = nil + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 319) + def _reduce_83(val, _values, result) + token = val[3] + token.alias = val[6] + result = val[0].append(token) + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 325) + def _reduce_84(val, _values, result) + if @prec_seen + raise "Multiple User_code after %prec" if @code_after_prec + @code_after_prec = true + end + @lexer.status = :c_declaration + @lexer.end_symbol = '}' + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 334) + def _reduce_85(val, _values, result) + @lexer.status = :initial + @lexer.end_symbol = nil + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 339) + def _reduce_86(val, _values, result) + token = val[2] + token.alias = val[5] + result = [token] + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 345) + def _reduce_87(val, _values, result) + sym = @grammar.find_symbol_by_id!(val[2]) + result = val[0].append(sym) + @prec_seen = true + + result + end +.,., + +# reduce 88 omitted + +module_eval(<<'.,.,', 'parser.y', 351) + def _reduce_89(val, _values, result) + result = val[1].s_value + result + end +.,., + +# reduce 90 omitted + +# reduce 91 omitted + +module_eval(<<'.,.,', 'parser.y', 358) + def _reduce_92(val, _values, result) + @lexer.status = :c_declaration + @lexer.end_symbol = '\Z' + @grammar.epilogue_first_lineno = @lexer.line + 1 + + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 364) + def _reduce_93(val, _values, result) + @lexer.status = :initial + @lexer.end_symbol = nil + @grammar.epilogue = val[2].s_value + + result + end +.,., + +# reduce 94 omitted + +# reduce 95 omitted + +# reduce 96 omitted + +# reduce 97 omitted + +# reduce 98 omitted + +module_eval(<<'.,.,', 'parser.y', 376) + def _reduce_99(val, _values, result) + result = [val[0]] + result + end +.,., + +module_eval(<<'.,.,', 'parser.y', 377) + def _reduce_100(val, _values, result) + result = val[0].append(val[1]) + result + end +.,., + +# reduce 101 omitted + +# reduce 102 omitted + +module_eval(<<'.,.,', 'parser.y', 382) + def _reduce_103(val, _values, result) + result = Lrama::Lexer::Token.new(type: Lrama::Lexer::Token::Ident, s_value: val[0]) + result + end +.,., + +def _reduce_none(val, _values, result) + val[0] end + + end # class Parser +end # module Lrama diff --git a/tool/lrama/lib/lrama/parser/token_scanner.rb b/tool/lrama/lib/lrama/parser/token_scanner.rb deleted file mode 100644 index 992b5742d3..0000000000 --- a/tool/lrama/lib/lrama/parser/token_scanner.rb +++ /dev/null @@ -1,56 +0,0 @@ -module Lrama - class Parser - class TokenScanner - def initialize(tokens) - @tokens = tokens - @index = 0 - end - - def current_token - @tokens[@index] - end - - def current_type - current_token&.type - end - - def previous_token - @tokens[@index - 1] - end - - def next - token = current_token - @index += 1 - return token - end - - def consume(*token_types) - if token_types.include?(current_type) - return self.next - end - - return nil - end - - def consume!(*token_types) - consume(*token_types) || (raise "#{token_types} is expected but #{current_type}. #{current_token}") - end - - def consume_multi(*token_types) - a = [] - - while token_types.include?(current_type) - a << self.next - end - - raise "No token is consumed. #{token_types}" if a.empty? - - return a - end - - def eots? - current_token.nil? - end - end - end -end diff --git a/tool/lrama/lib/lrama/version.rb b/tool/lrama/lib/lrama/version.rb index fe695873e5..bb4422bb97 100644 --- a/tool/lrama/lib/lrama/version.rb +++ b/tool/lrama/lib/lrama/version.rb @@ -1,3 +1,3 @@ module Lrama - VERSION = "0.5.6".freeze + VERSION = "0.5.7".freeze end diff --git a/tool/lrama/template/bison/_yacc.h b/tool/lrama/template/bison/_yacc.h new file mode 100644 index 0000000000..2af4d1e1b8 --- /dev/null +++ b/tool/lrama/template/bison/_yacc.h @@ -0,0 +1,71 @@ +<%# b4_shared_declarations -%> + <%-# b4_cpp_guard_open([b4_spec_mapped_header_file]) -%> + <%- if output.spec_mapped_header_file -%> +#ifndef <%= output.b4_cpp_guard__b4_spec_mapped_header_file %> +# define <%= output.b4_cpp_guard__b4_spec_mapped_header_file %> + <%- end -%> + <%-# b4_declare_yydebug & b4_YYDEBUG_define -%> +/* Debug traces. */ +#ifndef YYDEBUG +# define YYDEBUG 0 +#endif +#if YYDEBUG && !defined(yydebug) +extern int yydebug; +#endif + <%-# b4_percent_code_get([[requires]]). %code is not supported -%> + + <%-# b4_token_enums_defines -%> +/* Token kinds. */ +#ifndef YYTOKENTYPE +# define YYTOKENTYPE + enum yytokentype + { +<%= output.token_enums -%> + }; + typedef enum yytokentype yytoken_kind_t; +#endif + + <%-# b4_declare_yylstype -%> + <%-# b4_value_type_define -%> +/* Value type. */ +#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED +union YYSTYPE +{ +#line <%= output.grammar.union.lineno %> "<%= output.grammar_file_path %>" +<%= output.grammar.union.braces_less_code %> +#line [@oline@] [@ofile@] + +}; +typedef union YYSTYPE YYSTYPE; +# define YYSTYPE_IS_TRIVIAL 1 +# define YYSTYPE_IS_DECLARED 1 +#endif + + <%-# b4_location_type_define -%> +/* Location type. */ +#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED +typedef struct YYLTYPE YYLTYPE; +struct YYLTYPE +{ + int first_line; + int first_column; + int last_line; + int last_column; +}; +# define YYLTYPE_IS_DECLARED 1 +# define YYLTYPE_IS_TRIVIAL 1 +#endif + + + + + <%-# b4_declare_yyerror_and_yylex. Not supported -%> + <%-# b4_declare_yyparse -%> +int yyparse (<%= output.parse_param %>); + + + <%-# b4_percent_code_get([[provides]]). %code is not supported -%> + <%-# b4_cpp_guard_close([b4_spec_mapped_header_file]) -%> + <%- if output.spec_mapped_header_file -%> +#endif /* !<%= output.b4_cpp_guard__b4_spec_mapped_header_file %> */ + <%- end -%> diff --git a/tool/lrama/template/bison/yacc.c b/tool/lrama/template/bison/yacc.c index 8f57984ef3..840afc22a5 100644 --- a/tool/lrama/template/bison/yacc.c +++ b/tool/lrama/template/bison/yacc.c @@ -101,79 +101,13 @@ # endif <%# b4_header_include_if -%> +<%- if output.include_header -%> +#include "<%= output.include_header %>" +<%- else -%> /* Use api.header.include to #include this header instead of duplicating it here. */ -<%# b4_shared_declarations -%> - <%-# b4_cpp_guard_open([b4_spec_mapped_header_file]) -%> - <%- if output.spec_mapped_header_file -%> -#ifndef <%= output.b4_cpp_guard__b4_spec_mapped_header_file %> -# define <%= output.b4_cpp_guard__b4_spec_mapped_header_file %> - <%- end -%> - <%-# b4_declare_yydebug & b4_YYDEBUG_define -%> -/* Debug traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif -#if YYDEBUG && !defined(yydebug) -extern int yydebug; -#endif - <%-# b4_percent_code_get([[requires]]). %code is not supported -%> - - <%-# b4_token_enums_defines -%> -/* Token kinds. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - enum yytokentype - { -<%= output.token_enums -%> - }; - typedef enum yytokentype yytoken_kind_t; -#endif - - <%-# b4_declare_yylstype -%> - <%-# b4_value_type_define -%> -/* Value type. */ -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -union YYSTYPE -{ -#line <%= output.grammar.union.lineno %> "<%= output.grammar_file_path %>" -<%= output.grammar.union.braces_less_code %> -#line [@oline@] [@ofile@] - -}; -typedef union YYSTYPE YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 -# define YYSTYPE_IS_DECLARED 1 -#endif - - <%-# b4_location_type_define -%> -/* Location type. */ -#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED -typedef struct YYLTYPE YYLTYPE; -struct YYLTYPE -{ - int first_line; - int first_column; - int last_line; - int last_column; -}; -# define YYLTYPE_IS_DECLARED 1 -# define YYLTYPE_IS_TRIVIAL 1 -#endif - - - - - <%-# b4_declare_yyerror_and_yylex. Not supported -%> - <%-# b4_declare_yyparse -%> -int yyparse (<%= output.parse_param %>); - - - <%-# b4_percent_code_get([[provides]]). %code is not supported -%> - <%-# b4_cpp_guard_close([b4_spec_mapped_header_file]) -%> - <%- if output.spec_mapped_header_file -%> -#endif /* !<%= output.b4_cpp_guard__b4_spec_mapped_header_file %> */ - <%- end -%> +<%= output.render_partial("bison/_yacc.h") %> +<%- end -%> <%# b4_declare_symbol_enum -%> /* Symbol kind. */ enum yysymbol_kind_t @@ -2114,3 +2048,4 @@ yyreturnlab: #line <%= output.aux.epilogue_first_lineno - 1 %> "<%= output.grammar_file_path %>" <%= output.aux.epilogue -%> + diff --git a/tool/lrama/template/bison/yacc.h b/tool/lrama/template/bison/yacc.h index 932d6409db..848dbf5961 100644 --- a/tool/lrama/template/bison/yacc.h +++ b/tool/lrama/template/bison/yacc.h @@ -37,76 +37,4 @@ /* DO NOT RELY ON FEATURES THAT ARE NOT DOCUMENTED in the manual, especially those whose name start with YY_ or yy_. They are private implementation details that can be changed or removed. */ - -<%# b4_shared_declarations -%> -<%# b4_shared_declarations -%> - <%-# b4_cpp_guard_open([b4_spec_mapped_header_file]) -%> - <%- if output.spec_mapped_header_file -%> -#ifndef <%= output.b4_cpp_guard__b4_spec_mapped_header_file %> -# define <%= output.b4_cpp_guard__b4_spec_mapped_header_file %> - <%- end -%> - <%-# b4_declare_yydebug & b4_YYDEBUG_define -%> -/* Debug traces. */ -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif -#if YYDEBUG -extern int yydebug; -#endif - <%-# b4_percent_code_get([[requires]]). %code is not supported -%> - - <%-# b4_token_enums_defines -%> -/* Token kinds. */ -#ifndef YYTOKENTYPE -# define YYTOKENTYPE - enum yytokentype - { -<%= output.token_enums -%> - }; - typedef enum yytokentype yytoken_kind_t; -#endif - - <%-# b4_declare_yylstype -%> - <%-# b4_value_type_define -%> -/* Value type. */ -#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED -union YYSTYPE -{ -#line <%= output.grammar.union.lineno %> "<%= output.grammar_file_path %>" -<%= output.grammar.union.braces_less_code %> -#line [@oline@] [@ofile@] - -}; -typedef union YYSTYPE YYSTYPE; -# define YYSTYPE_IS_TRIVIAL 1 -# define YYSTYPE_IS_DECLARED 1 -#endif - - <%-# b4_location_type_define -%> -/* Location type. */ -#if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED -typedef struct YYLTYPE YYLTYPE; -struct YYLTYPE -{ - int first_line; - int first_column; - int last_line; - int last_column; -}; -# define YYLTYPE_IS_DECLARED 1 -# define YYLTYPE_IS_TRIVIAL 1 -#endif - - - - - <%-# b4_declare_yyerror_and_yylex. Not supported -%> - <%-# b4_declare_yyparse -%> -int yyparse (<%= output.parse_param %>); - - - <%-# b4_percent_code_get([[provides]]). %code is not supported -%> - <%-# b4_cpp_guard_close([b4_spec_mapped_header_file]) -%> - <%- if output.spec_mapped_header_file -%> -#endif /* !<%= output.b4_cpp_guard__b4_spec_mapped_header_file %> */ - <%- end -%> +<%= output.render_partial("bison/_yacc.h") %> -- cgit v1.2.3