aboutsummaryrefslogtreecommitdiffstats
path: root/tool
diff options
context:
space:
mode:
authoryui-knk <spiketeika@gmail.com>2023-10-23 09:07:23 +0900
committerYuichiro Kaneko <spiketeika@gmail.com>2023-10-23 13:14:15 +0900
commit2d468358a516f575d013f07801079e0906c61f0c (patch)
tree609afdf2ba961d7c8079bb22ea4fe2b94500abcb /tool
parentdd9b4851a335888f971f09322f25ed63c5b2f587 (diff)
downloadruby-2d468358a516f575d013f07801079e0906c61f0c.tar.gz
Lrama v0.5.7
Diffstat (limited to 'tool')
-rw-r--r--tool/lrama/lib/lrama/command.rb3
-rw-r--r--tool/lrama/lib/lrama/context.rb8
-rw-r--r--tool/lrama/lib/lrama/digraph.rb3
-rw-r--r--tool/lrama/lib/lrama/grammar.rb188
-rw-r--r--tool/lrama/lib/lrama/grammar/union.rb4
-rw-r--r--tool/lrama/lib/lrama/lexer.rb434
-rw-r--r--tool/lrama/lib/lrama/option_parser.rb6
-rw-r--r--tool/lrama/lib/lrama/output.rb42
-rw-r--r--tool/lrama/lib/lrama/parser.rb2014
-rw-r--r--tool/lrama/lib/lrama/parser/token_scanner.rb56
-rw-r--r--tool/lrama/lib/lrama/version.rb2
-rw-r--r--tool/lrama/template/bison/_yacc.h71
-rw-r--r--tool/lrama/template/bison/yacc.c77
-rw-r--r--tool/lrama/template/bison/yacc.h74
14 files changed, 2197 insertions, 785 deletions
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_]+>)?\$/) # $$, $<long>$
+ 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, $<long>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, $<long>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, $<long>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_]+>)?\$/) # $$, $<long>$
+ 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, $<long>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, $<long>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, $<long>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_]+>)?\$/) # $$, $<long>$
+ 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, $<long>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, $<long>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, $<long>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_]+>)?\$/) # $$, $<long>$
+ 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, $<long>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, $<long>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, $<long>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_]+>)?\$/) # $$, $<long>$
- 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, $<long>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, $<long>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, $<long>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 [-o<var>filename</var>] [--output-file=<var>filename</var>]
+# [-e<var>rubypath</var>] [--executable=<var>rubypath</var>]
+# [-v] [--verbose]
+# [-O<var>filename</var>] [--log-file=<var>filename</var>]
+# [-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] <var>grammarfile</var>
+#
+# [+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, <code>yyparse(obj, :scan)</code> 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 <id> '\\' "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 ' <none>'
+ 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") %>