Lrama v0.5.5
This commit is contained in:
parent
fd0df1f8c6
commit
c02f978fd5
Notes:
git
2023-08-28 23:26:40 +00:00
@ -1,6 +1,5 @@
|
|||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
|
|
||||||
$LOAD_PATH << File.join(__dir__, "../lib")
|
$LOAD_PATH << File.join(__dir__, "../lib")
|
||||||
require "lrama"
|
require "lrama"
|
||||||
|
|
||||||
|
@ -5,7 +5,6 @@ module Lrama
|
|||||||
def initialize(argv)
|
def initialize(argv)
|
||||||
@argv = argv
|
@argv = argv
|
||||||
|
|
||||||
@version = nil
|
|
||||||
@skeleton = "bison/yacc.c"
|
@skeleton = "bison/yacc.c"
|
||||||
@header = false
|
@header = false
|
||||||
@header_file = nil
|
@header_file = nil
|
||||||
@ -23,15 +22,11 @@ module Lrama
|
|||||||
def run
|
def run
|
||||||
parse_option
|
parse_option
|
||||||
|
|
||||||
if @version
|
|
||||||
puts Lrama::VERSION
|
|
||||||
exit 0
|
|
||||||
end
|
|
||||||
|
|
||||||
Report::Duration.enable if @trace_opts[:time]
|
Report::Duration.enable if @trace_opts[:time]
|
||||||
|
|
||||||
warning = Lrama::Warning.new
|
warning = Lrama::Warning.new
|
||||||
grammar = Lrama::Parser.new(@y.read).parse
|
grammar = Lrama::Parser.new(@y.read).parse
|
||||||
|
@y.close if @y != STDIN
|
||||||
states = Lrama::States.new(grammar, warning, trace_state: (@trace_opts[:automaton] || @trace_opts[:closure]))
|
states = Lrama::States.new(grammar, warning, trace_state: (@trace_opts[:automaton] || @trace_opts[:closure]))
|
||||||
states.compute
|
states.compute
|
||||||
context = Lrama::Context.new(states)
|
context = Lrama::Context.new(states)
|
||||||
@ -112,7 +107,7 @@ module Lrama
|
|||||||
opt = OptionParser.new
|
opt = OptionParser.new
|
||||||
|
|
||||||
# opt.on('-h') {|v| p v }
|
# opt.on('-h') {|v| p v }
|
||||||
opt.on('-V', '--version') {|v| @version = true }
|
opt.on('-V', '--version') {|v| puts "lrama #{Lrama::VERSION}"; exit 0 }
|
||||||
|
|
||||||
# Tuning the Parser
|
# Tuning the Parser
|
||||||
opt.on('-S', '--skeleton=FILE') {|v| @skeleton = v }
|
opt.on('-S', '--skeleton=FILE') {|v| @skeleton = v }
|
||||||
|
@ -401,7 +401,6 @@ module Lrama
|
|||||||
end
|
end
|
||||||
print sprintf("]\n\n")
|
print sprintf("]\n\n")
|
||||||
|
|
||||||
|
|
||||||
print sprintf("width [\n")
|
print sprintf("width [\n")
|
||||||
vectors_count.times do |i|
|
vectors_count.times do |i|
|
||||||
print sprintf("%d, ", ary[i] ? ary[i][3] : 0)
|
print sprintf("%d, ", ary[i] ? ary[i][3] : 0)
|
||||||
@ -409,7 +408,6 @@ module Lrama
|
|||||||
end
|
end
|
||||||
print sprintf("]\n\n")
|
print sprintf("]\n\n")
|
||||||
|
|
||||||
|
|
||||||
print sprintf("tally [\n")
|
print sprintf("tally [\n")
|
||||||
vectors_count.times do |i|
|
vectors_count.times do |i|
|
||||||
print sprintf("%d, ", ary[i] ? ary[i][2] : 0)
|
print sprintf("%d, ", ary[i] ? ary[i][2] : 0)
|
||||||
|
@ -205,7 +205,7 @@ module Lrama
|
|||||||
end
|
end
|
||||||
|
|
||||||
def build_paths_from_state_items(state_items)
|
def build_paths_from_state_items(state_items)
|
||||||
paths = state_items.zip([nil] + state_items).map do |si, prev_si|
|
state_items.zip([nil] + state_items).map do |si, prev_si|
|
||||||
case
|
case
|
||||||
when prev_si.nil?
|
when prev_si.nil?
|
||||||
StartPath.new(si)
|
StartPath.new(si)
|
||||||
@ -215,8 +215,6 @@ module Lrama
|
|||||||
TransitionPath.new(prev_si, si)
|
TransitionPath.new(prev_si, si)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
paths
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def shortest_path(conflict_state, conflict_reduce_item, conflict_term)
|
def shortest_path(conflict_state, conflict_reduce_item, conflict_term)
|
||||||
|
@ -103,6 +103,10 @@ module Lrama
|
|||||||
set_precedence(sym, Precedence.new(type: :right, precedence: precedence))
|
set_precedence(sym, Precedence.new(type: :right, precedence: precedence))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def add_precedence(sym, precedence)
|
||||||
|
set_precedence(sym, Precedence.new(type: :precedence, precedence: precedence))
|
||||||
|
end
|
||||||
|
|
||||||
def set_precedence(sym, precedence)
|
def set_precedence(sym, precedence)
|
||||||
raise "" if sym.nterm?
|
raise "" if sym.nterm?
|
||||||
sym.precedence = precedence
|
sym.precedence = precedence
|
||||||
@ -310,7 +314,6 @@ module Lrama
|
|||||||
end || (raise "Nterm not found: #{id}")
|
end || (raise "Nterm not found: #{id}")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def append_special_symbols
|
def append_special_symbols
|
||||||
# YYEMPTY (token_id: -2, number: -2) is added when a template is evaluated
|
# YYEMPTY (token_id: -2, number: -2) is added when a template is evaluated
|
||||||
# term = add_term(id: Token.new(Token::Ident, "YYEMPTY"), token_id: -2)
|
# term = add_term(id: Token.new(Token::Ident, "YYEMPTY"), token_id: -2)
|
||||||
@ -512,7 +515,7 @@ module Lrama
|
|||||||
sym.token_id = 11
|
sym.token_id = 11
|
||||||
when "\""
|
when "\""
|
||||||
sym.token_id = 34
|
sym.token_id = 34
|
||||||
when "\'"
|
when "'"
|
||||||
sym.token_id = 39
|
sym.token_id = 39
|
||||||
when "\\\\"
|
when "\\\\"
|
||||||
sym.token_id = 92
|
sym.token_id = 92
|
||||||
|
@ -50,7 +50,6 @@ module Lrama
|
|||||||
end
|
end
|
||||||
alias :translated_error_token_code :translated_printer_code
|
alias :translated_error_token_code :translated_printer_code
|
||||||
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# * ($1) yyvsp[i]
|
# * ($1) yyvsp[i]
|
||||||
|
@ -30,7 +30,6 @@ module Lrama
|
|||||||
@grammar_rules = []
|
@grammar_rules = []
|
||||||
@epilogue = []
|
@epilogue = []
|
||||||
|
|
||||||
#
|
|
||||||
@bison_declarations_tokens = []
|
@bison_declarations_tokens = []
|
||||||
@grammar_rules_tokens = []
|
@grammar_rules_tokens = []
|
||||||
|
|
||||||
@ -155,6 +154,8 @@ module Lrama
|
|||||||
tokens << create_token(Token::P_left, ss[0], line, ss.pos - column)
|
tokens << create_token(Token::P_left, ss[0], line, ss.pos - column)
|
||||||
when ss.scan(/%right/)
|
when ss.scan(/%right/)
|
||||||
tokens << create_token(Token::P_right, ss[0], line, ss.pos - column)
|
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/)
|
when ss.scan(/%prec/)
|
||||||
tokens << create_token(Token::P_prec, ss[0], line, ss.pos - column)
|
tokens << create_token(Token::P_prec, ss[0], line, ss.pos - column)
|
||||||
when ss.scan(/{/)
|
when ss.scan(/{/)
|
||||||
@ -223,7 +224,7 @@ module Lrama
|
|||||||
references << [:dollar, ss[2], tag, str.length, str.length + ss[0].length - 1]
|
references << [:dollar, ss[2], tag, str.length, str.length + ss[0].length - 1]
|
||||||
when ss.scan(/@\$/) # @$
|
when ss.scan(/@\$/) # @$
|
||||||
references << [:at, "$", nil, str.length, str.length + ss[0].length - 1]
|
references << [:at, "$", nil, str.length, str.length + ss[0].length - 1]
|
||||||
when ss.scan(/@(\d)+/) # @1
|
when ss.scan(/@(\d+)/) # @1
|
||||||
references << [:at, Integer(ss[1]), nil, str.length, str.length + ss[0].length - 1]
|
references << [:at, Integer(ss[1]), nil, str.length, str.length + ss[0].length - 1]
|
||||||
when ss.scan(/{/)
|
when ss.scan(/{/)
|
||||||
brace_count += 1
|
brace_count += 1
|
||||||
@ -314,8 +315,6 @@ module Lrama
|
|||||||
str << ss.getch
|
str << ss.getch
|
||||||
next
|
next
|
||||||
end
|
end
|
||||||
|
|
||||||
str << ss[0]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
line # Reach to end of input
|
line # Reach to end of input
|
||||||
|
@ -61,6 +61,7 @@ module Lrama
|
|||||||
define_type(:P_nonassoc) # %nonassoc
|
define_type(:P_nonassoc) # %nonassoc
|
||||||
define_type(:P_left) # %left
|
define_type(:P_left) # %left
|
||||||
define_type(:P_right) # %right
|
define_type(:P_right) # %right
|
||||||
|
define_type(:P_precedence) # %precedence
|
||||||
define_type(:P_prec) # %prec
|
define_type(:P_prec) # %prec
|
||||||
define_type(:User_code) # { ... }
|
define_type(:User_code) # { ... }
|
||||||
define_type(:Tag) # <int>
|
define_type(:Tag) # <int>
|
||||||
|
@ -252,7 +252,7 @@ module Lrama
|
|||||||
end
|
end
|
||||||
|
|
||||||
def extract_param_name(param)
|
def extract_param_name(param)
|
||||||
/\A(\W*)([a-zA-Z0-9_]+)\z/.match(param.split.last)[2]
|
param[/\b([a-zA-Z0-9_]+)(?=\s*\z)/]
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_param_name
|
def parse_param_name
|
||||||
|
@ -159,6 +159,14 @@ module Lrama
|
|||||||
grammar.add_right(sym, precedence_number)
|
grammar.add_right(sym, precedence_number)
|
||||||
end
|
end
|
||||||
precedence_number += 1
|
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)
|
||||||
|
end
|
||||||
|
precedence_number += 1
|
||||||
when nil
|
when nil
|
||||||
# end of input
|
# end of input
|
||||||
raise "Reach to end of input within declarations"
|
raise "Reach to end of input within declarations"
|
||||||
|
@ -62,7 +62,6 @@ module Lrama
|
|||||||
@items_to_state[items] = next_state
|
@items_to_state[items] = next_state
|
||||||
end
|
end
|
||||||
|
|
||||||
#
|
|
||||||
def set_look_ahead(rule, look_ahead)
|
def set_look_ahead(rule, look_ahead)
|
||||||
reduce = reduces.find do |r|
|
reduce = reduces.find do |r|
|
||||||
r.rule == rule
|
r.rule == rule
|
||||||
|
@ -455,6 +455,11 @@ module Lrama
|
|||||||
|
|
||||||
# shift_prec == reduce_prec, then check associativity
|
# shift_prec == reduce_prec, then check associativity
|
||||||
case sym.precedence.type
|
case sym.precedence.type
|
||||||
|
when :precedence
|
||||||
|
# %precedence only specifies precedence and not specify associativity
|
||||||
|
# then a conflict is unresolved if precedence is same.
|
||||||
|
state.conflicts << State::ShiftReduceConflict.new(symbols: [sym], shift: shift, reduce: reduce)
|
||||||
|
next
|
||||||
when :right
|
when :right
|
||||||
# Shift is selected
|
# Shift is selected
|
||||||
state.resolved_conflicts << State::ResolvedConflict.new(symbol: sym, reduce: reduce, which: :shift, same_prec: true)
|
state.resolved_conflicts << State::ResolvedConflict.new(symbol: sym, reduce: reduce, which: :shift, same_prec: true)
|
||||||
@ -515,9 +520,9 @@ module Lrama
|
|||||||
|
|
||||||
state.default_reduction_rule = state.reduces.map do |r|
|
state.default_reduction_rule = state.reduces.map do |r|
|
||||||
[r.rule, r.rule.id, (r.look_ahead || []).count]
|
[r.rule, r.rule.id, (r.look_ahead || []).count]
|
||||||
end.sort_by do |rule, rule_id, count|
|
end.min_by do |rule, rule_id, count|
|
||||||
[-count, rule_id]
|
[-count, rule_id]
|
||||||
end.first.first
|
end.first
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -110,7 +110,6 @@ module Lrama
|
|||||||
end
|
end
|
||||||
io << "\n"
|
io << "\n"
|
||||||
|
|
||||||
|
|
||||||
# Report shifts
|
# Report shifts
|
||||||
tmp = state.term_transitions.select do |shift, _|
|
tmp = state.term_transitions.select do |shift, _|
|
||||||
!shift.not_selected
|
!shift.not_selected
|
||||||
@ -123,7 +122,6 @@ module Lrama
|
|||||||
end
|
end
|
||||||
io << "\n" if !tmp.empty?
|
io << "\n" if !tmp.empty?
|
||||||
|
|
||||||
|
|
||||||
# Report error caused by %nonassoc
|
# Report error caused by %nonassoc
|
||||||
nl = false
|
nl = false
|
||||||
tmp = state.resolved_conflicts.select do |resolved|
|
tmp = state.resolved_conflicts.select do |resolved|
|
||||||
@ -138,7 +136,6 @@ module Lrama
|
|||||||
end
|
end
|
||||||
io << "\n" if !tmp.empty?
|
io << "\n" if !tmp.empty?
|
||||||
|
|
||||||
|
|
||||||
# Report reduces
|
# Report reduces
|
||||||
nl = false
|
nl = false
|
||||||
max_len = state.non_default_reduces.flat_map(&:look_ahead).compact.map(&:display_name).map(&:length).max || 0
|
max_len = state.non_default_reduces.flat_map(&:look_ahead).compact.map(&:display_name).map(&:length).max || 0
|
||||||
@ -171,7 +168,6 @@ module Lrama
|
|||||||
end
|
end
|
||||||
io << "\n" if nl
|
io << "\n" if nl
|
||||||
|
|
||||||
|
|
||||||
# Report nonterminal transitions
|
# Report nonterminal transitions
|
||||||
tmp = []
|
tmp = []
|
||||||
max_len = 0
|
max_len = 0
|
||||||
@ -189,7 +185,6 @@ module Lrama
|
|||||||
end
|
end
|
||||||
io << "\n" if !tmp.empty?
|
io << "\n" if !tmp.empty?
|
||||||
|
|
||||||
|
|
||||||
if solved
|
if solved
|
||||||
# Report conflict resolutions
|
# Report conflict resolutions
|
||||||
state.resolved_conflicts.each do |resolved|
|
state.resolved_conflicts.each do |resolved|
|
||||||
@ -207,8 +202,8 @@ module Lrama
|
|||||||
label2 = example.type == :shift_reduce ? "Reduce derivation" : "Second Reduce derivation"
|
label2 = example.type == :shift_reduce ? "Reduce derivation" : "Second Reduce derivation"
|
||||||
|
|
||||||
io << " #{label0} conflict on token #{example.conflict_symbol.id.s_value}:\n"
|
io << " #{label0} conflict on token #{example.conflict_symbol.id.s_value}:\n"
|
||||||
io << " #{example.path1_item.to_s}\n"
|
io << " #{example.path1_item}\n"
|
||||||
io << " #{example.path2_item.to_s}\n"
|
io << " #{example.path2_item}\n"
|
||||||
io << " #{label1}\n"
|
io << " #{label1}\n"
|
||||||
example.derivations1.render_strings_for_report.each do |str|
|
example.derivations1.render_strings_for_report.each do |str|
|
||||||
io << " #{str}\n"
|
io << " #{str}\n"
|
||||||
@ -234,7 +229,6 @@ module Lrama
|
|||||||
end
|
end
|
||||||
io << "\n"
|
io << "\n"
|
||||||
|
|
||||||
|
|
||||||
# Report reads_relation
|
# Report reads_relation
|
||||||
io << " [Reads Relation]\n"
|
io << " [Reads Relation]\n"
|
||||||
@states.nterms.each do |nterm|
|
@states.nterms.each do |nterm|
|
||||||
@ -248,7 +242,6 @@ module Lrama
|
|||||||
end
|
end
|
||||||
io << "\n"
|
io << "\n"
|
||||||
|
|
||||||
|
|
||||||
# Report read_sets
|
# Report read_sets
|
||||||
io << " [Read sets]\n"
|
io << " [Read sets]\n"
|
||||||
read_sets = @states.read_sets
|
read_sets = @states.read_sets
|
||||||
@ -263,7 +256,6 @@ module Lrama
|
|||||||
end
|
end
|
||||||
io << "\n"
|
io << "\n"
|
||||||
|
|
||||||
|
|
||||||
# Report includes_relation
|
# Report includes_relation
|
||||||
io << " [Includes Relation]\n"
|
io << " [Includes Relation]\n"
|
||||||
@states.nterms.each do |nterm|
|
@states.nterms.each do |nterm|
|
||||||
@ -277,7 +269,6 @@ module Lrama
|
|||||||
end
|
end
|
||||||
io << "\n"
|
io << "\n"
|
||||||
|
|
||||||
|
|
||||||
# Report lookback_relation
|
# Report lookback_relation
|
||||||
io << " [Lookback Relation]\n"
|
io << " [Lookback Relation]\n"
|
||||||
@states.rules.each do |rule|
|
@states.rules.each do |rule|
|
||||||
@ -286,12 +277,11 @@ module Lrama
|
|||||||
|
|
||||||
a.each do |state_id2, nterm_id2|
|
a.each do |state_id2, nterm_id2|
|
||||||
n = @states.nterms.find {|n| n.token_id == nterm_id2 }
|
n = @states.nterms.find {|n| n.token_id == nterm_id2 }
|
||||||
io << " (Rule: #{rule.to_s}) -> (State #{state_id2}, #{n.id.s_value})\n"
|
io << " (Rule: #{rule}) -> (State #{state_id2}, #{n.id.s_value})\n"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
io << "\n"
|
io << "\n"
|
||||||
|
|
||||||
|
|
||||||
# Report follow_sets
|
# Report follow_sets
|
||||||
io << " [Follow sets]\n"
|
io << " [Follow sets]\n"
|
||||||
follow_sets = @states.follow_sets
|
follow_sets = @states.follow_sets
|
||||||
@ -306,7 +296,6 @@ module Lrama
|
|||||||
end
|
end
|
||||||
io << "\n"
|
io << "\n"
|
||||||
|
|
||||||
|
|
||||||
# Report LA
|
# Report LA
|
||||||
io << " [Look-Ahead Sets]\n"
|
io << " [Look-Ahead Sets]\n"
|
||||||
tmp = []
|
tmp = []
|
||||||
@ -326,7 +315,6 @@ module Lrama
|
|||||||
io << "\n" if !tmp.empty?
|
io << "\n" if !tmp.empty?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
# End of Report State
|
# End of Report State
|
||||||
io << "\n"
|
io << "\n"
|
||||||
end
|
end
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
module Lrama
|
module Lrama
|
||||||
VERSION = "0.5.4".freeze
|
VERSION = "0.5.5".freeze
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user