Lrama v0.6.6
This commit is contained in:
parent
2ba7c1b142
commit
bf1f16ef47
@ -47,6 +47,11 @@ module Lrama
|
|||||||
puts grammar.rules
|
puts grammar.rules
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if options.trace_opts && options.trace_opts[:actions]
|
||||||
|
puts "Grammar rules with actions:"
|
||||||
|
grammar.rules.each { |rule| puts rule.with_actions }
|
||||||
|
end
|
||||||
|
|
||||||
File.open(options.outfile, "w+") do |f|
|
File.open(options.outfile, "w+") do |f|
|
||||||
Lrama::Output.new(
|
Lrama::Output.new(
|
||||||
out: f,
|
out: f,
|
||||||
|
@ -13,8 +13,12 @@ module Lrama
|
|||||||
@rules << rule
|
@rules << rule
|
||||||
end
|
end
|
||||||
|
|
||||||
def find(token)
|
def find_rule(token)
|
||||||
select_rules(token).last
|
select_rules(@rules, token).last
|
||||||
|
end
|
||||||
|
|
||||||
|
def find_inline(token)
|
||||||
|
@rules.select { |rule| rule.name == token.s_value && rule.is_inline }.last
|
||||||
end
|
end
|
||||||
|
|
||||||
def created_lhs(lhs_s_value)
|
def created_lhs(lhs_s_value)
|
||||||
@ -23,8 +27,9 @@ module Lrama
|
|||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def select_rules(token)
|
def select_rules(rules, token)
|
||||||
rules = select_rules_by_name(token.rule_name)
|
rules = select_not_inline_rules(rules)
|
||||||
|
rules = select_rules_by_name(rules, token.rule_name)
|
||||||
rules = rules.select { |rule| rule.required_parameters_count == token.args_count }
|
rules = rules.select { |rule| rule.required_parameters_count == token.args_count }
|
||||||
if rules.empty?
|
if rules.empty?
|
||||||
raise "Invalid number of arguments. `#{token.rule_name}`"
|
raise "Invalid number of arguments. `#{token.rule_name}`"
|
||||||
@ -33,8 +38,12 @@ module Lrama
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def select_rules_by_name(rule_name)
|
def select_not_inline_rules(rules)
|
||||||
rules = @rules.select { |rule| rule.name == rule_name }
|
rules.select { |rule| !rule.is_inline }
|
||||||
|
end
|
||||||
|
|
||||||
|
def select_rules_by_name(rules, rule_name)
|
||||||
|
rules = rules.select { |rule| rule.name == rule_name }
|
||||||
if rules.empty?
|
if rules.empty?
|
||||||
raise "Parameterizing rule does not exist. `#{rule_name}`"
|
raise "Parameterizing rule does not exist. `#{rule_name}`"
|
||||||
else
|
else
|
||||||
|
@ -2,12 +2,13 @@ module Lrama
|
|||||||
class Grammar
|
class Grammar
|
||||||
class ParameterizingRule
|
class ParameterizingRule
|
||||||
class Rule
|
class Rule
|
||||||
attr_reader :name, :parameters, :rhs_list, :required_parameters_count
|
attr_reader :name, :parameters, :rhs_list, :required_parameters_count, :is_inline
|
||||||
|
|
||||||
def initialize(name, parameters, rhs_list)
|
def initialize(name, parameters, rhs_list, is_inline: false)
|
||||||
@name = name
|
@name = name
|
||||||
@parameters = parameters
|
@parameters = parameters
|
||||||
@rhs_list = rhs_list
|
@rhs_list = rhs_list
|
||||||
|
@is_inline = is_inline
|
||||||
@required_parameters_count = parameters.count
|
@required_parameters_count = parameters.count
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -19,7 +19,7 @@ module Lrama
|
|||||||
# TODO: Change this to display_name
|
# TODO: Change this to display_name
|
||||||
def to_s
|
def to_s
|
||||||
l = lhs.id.s_value
|
l = lhs.id.s_value
|
||||||
r = empty_rule? ? "ε" : rhs.map {|r| r.id.s_value }.join(", ")
|
r = empty_rule? ? "ε" : rhs.map {|r| r.id.s_value }.join(" ")
|
||||||
|
|
||||||
"#{l} -> #{r}"
|
"#{l} -> #{r}"
|
||||||
end
|
end
|
||||||
@ -32,6 +32,10 @@ module Lrama
|
|||||||
"#{l}: #{r}"
|
"#{l}: #{r}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def with_actions
|
||||||
|
"#{to_s} {#{token_code&.s_value}}"
|
||||||
|
end
|
||||||
|
|
||||||
# opt_nl: ε <-- empty_rule
|
# opt_nl: ε <-- empty_rule
|
||||||
# | '\n' <-- not empty_rule
|
# | '\n' <-- not empty_rule
|
||||||
def empty_rule?
|
def empty_rule?
|
||||||
|
@ -16,8 +16,13 @@ module Lrama
|
|||||||
@user_code = nil
|
@user_code = nil
|
||||||
@precedence_sym = nil
|
@precedence_sym = nil
|
||||||
@line = nil
|
@line = nil
|
||||||
|
@rules = []
|
||||||
@rule_builders_for_parameterizing_rules = []
|
@rule_builders_for_parameterizing_rules = []
|
||||||
@rule_builders_for_derived_rules = []
|
@rule_builders_for_derived_rules = []
|
||||||
|
@rule_builders_for_inline_rules = []
|
||||||
|
@parameterizing_rules = []
|
||||||
|
@inline_rules = []
|
||||||
|
@midrule_action_rules = []
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_rhs(rhs)
|
def add_rhs(rhs)
|
||||||
@ -52,12 +57,16 @@ module Lrama
|
|||||||
|
|
||||||
def setup_rules(parameterizing_rule_resolver)
|
def setup_rules(parameterizing_rule_resolver)
|
||||||
preprocess_references unless @skip_preprocess_references
|
preprocess_references unless @skip_preprocess_references
|
||||||
|
if rhs.any? { |token| parameterizing_rule_resolver.find_inline(token) }
|
||||||
|
resolve_inline(parameterizing_rule_resolver)
|
||||||
|
else
|
||||||
process_rhs(parameterizing_rule_resolver)
|
process_rhs(parameterizing_rule_resolver)
|
||||||
|
end
|
||||||
build_rules
|
build_rules
|
||||||
end
|
end
|
||||||
|
|
||||||
def rules
|
def rules
|
||||||
@parameterizing_rules + @midrule_action_rules + @rules
|
@parameterizing_rules + @inline_rules + @midrule_action_rules + @rules
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
@ -73,6 +82,7 @@ module Lrama
|
|||||||
def build_rules
|
def build_rules
|
||||||
tokens = @replaced_rhs
|
tokens = @replaced_rhs
|
||||||
|
|
||||||
|
if tokens
|
||||||
rule = Rule.new(
|
rule = Rule.new(
|
||||||
id: @rule_counter.increment, _lhs: lhs, _rhs: tokens, lhs_tag: lhs_tag, token_code: user_code,
|
id: @rule_counter.increment, _lhs: lhs, _rhs: tokens, lhs_tag: lhs_tag, token_code: user_code,
|
||||||
position_in_original_rule_rhs: @position_in_original_rule_rhs, precedence_sym: precedence_sym, lineno: line
|
position_in_original_rule_rhs: @position_in_original_rule_rhs, precedence_sym: precedence_sym, lineno: line
|
||||||
@ -87,6 +97,11 @@ module Lrama
|
|||||||
@midrule_action_rules.each do |r|
|
@midrule_action_rules.each do |r|
|
||||||
r.original_rule = rule
|
r.original_rule = rule
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
@inline_rules = @rule_builders_for_inline_rules.map do |rule_builder|
|
||||||
|
rule_builder.rules
|
||||||
|
end.flatten
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# rhs is a mixture of variety type of tokens like `Ident`, `InstantiateRule`, `UserCode` and so on.
|
# rhs is a mixture of variety type of tokens like `Ident`, `InstantiateRule`, `UserCode` and so on.
|
||||||
@ -103,7 +118,7 @@ module Lrama
|
|||||||
when Lrama::Lexer::Token::Ident
|
when Lrama::Lexer::Token::Ident
|
||||||
@replaced_rhs << token
|
@replaced_rhs << token
|
||||||
when Lrama::Lexer::Token::InstantiateRule
|
when Lrama::Lexer::Token::InstantiateRule
|
||||||
parameterizing_rule = parameterizing_rule_resolver.find(token)
|
parameterizing_rule = parameterizing_rule_resolver.find_rule(token)
|
||||||
raise "Unexpected token. #{token}" unless parameterizing_rule
|
raise "Unexpected token. #{token}" unless parameterizing_rule
|
||||||
|
|
||||||
bindings = Binding.new(parameterizing_rule, token.args)
|
bindings = Binding.new(parameterizing_rule, token.args)
|
||||||
@ -115,7 +130,7 @@ module Lrama
|
|||||||
@replaced_rhs << lhs_token
|
@replaced_rhs << lhs_token
|
||||||
parameterizing_rule_resolver.created_lhs_list << lhs_token
|
parameterizing_rule_resolver.created_lhs_list << lhs_token
|
||||||
parameterizing_rule.rhs_list.each do |r|
|
parameterizing_rule.rhs_list.each do |r|
|
||||||
rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, lhs_tag: token.lhs_tag, skip_preprocess_references: true)
|
rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, lhs_tag: token.lhs_tag)
|
||||||
rule_builder.lhs = lhs_token
|
rule_builder.lhs = lhs_token
|
||||||
r.symbols.each { |sym| rule_builder.add_rhs(bindings.resolve_symbol(sym)) }
|
r.symbols.each { |sym| rule_builder.add_rhs(bindings.resolve_symbol(sym)) }
|
||||||
rule_builder.line = line
|
rule_builder.line = line
|
||||||
@ -157,6 +172,41 @@ module Lrama
|
|||||||
"#{token.rule_name}_#{s_values.join('_')}"
|
"#{token.rule_name}_#{s_values.join('_')}"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def resolve_inline(parameterizing_rule_resolver)
|
||||||
|
rhs.each_with_index do |token, i|
|
||||||
|
if inline_rule = parameterizing_rule_resolver.find_inline(token)
|
||||||
|
inline_rule.rhs_list.each_with_index do |inline_rhs|
|
||||||
|
rule_builder = RuleBuilder.new(@rule_counter, @midrule_action_counter, lhs_tag: lhs_tag, skip_preprocess_references: true)
|
||||||
|
resolve_inline_rhs(rule_builder, inline_rhs, i)
|
||||||
|
rule_builder.lhs = lhs
|
||||||
|
rule_builder.line = line
|
||||||
|
rule_builder.user_code = replace_inline_user_code(inline_rhs, i)
|
||||||
|
rule_builder.complete_input
|
||||||
|
rule_builder.setup_rules(parameterizing_rule_resolver)
|
||||||
|
@rule_builders_for_inline_rules << rule_builder
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def resolve_inline_rhs(rule_builder, inline_rhs, index)
|
||||||
|
rhs.each_with_index do |token, i|
|
||||||
|
if index == i
|
||||||
|
inline_rhs.symbols.each { |sym| rule_builder.add_rhs(sym) }
|
||||||
|
else
|
||||||
|
rule_builder.add_rhs(token)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def replace_inline_user_code(inline_rhs, index)
|
||||||
|
return user_code if inline_rhs.user_code.nil?
|
||||||
|
return user_code if user_code.nil?
|
||||||
|
|
||||||
|
code = user_code.s_value.gsub(/\$#{index + 1}/, inline_rhs.user_code.s_value)
|
||||||
|
Lrama::Lexer::Token::UserCode.new(s_value: code, location: user_code.location)
|
||||||
|
end
|
||||||
|
|
||||||
def numberize_references
|
def numberize_references
|
||||||
# Bison n'th component is 1-origin
|
# Bison n'th component is 1-origin
|
||||||
(rhs + [user_code]).compact.each.with_index(1) do |token, i|
|
(rhs + [user_code]).compact.each.with_index(1) do |token, i|
|
||||||
|
@ -37,6 +37,7 @@ module Lrama
|
|||||||
%code
|
%code
|
||||||
%rule
|
%rule
|
||||||
%no-stdlib
|
%no-stdlib
|
||||||
|
%inline
|
||||||
)
|
)
|
||||||
|
|
||||||
def initialize(grammar_file)
|
def initialize(grammar_file)
|
||||||
|
@ -1,11 +1,21 @@
|
|||||||
module Lrama
|
module Lrama
|
||||||
class Lexer
|
class Lexer
|
||||||
class GrammarFile
|
class GrammarFile
|
||||||
|
class Text < String
|
||||||
|
def inspect
|
||||||
|
length <= 50 ? super : "#{self[0..47]}...".inspect
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
attr_reader :path, :text
|
attr_reader :path, :text
|
||||||
|
|
||||||
def initialize(path, text)
|
def initialize(path, text)
|
||||||
@path = path
|
@path = path
|
||||||
@text = text.freeze
|
@text = Text.new(text).freeze
|
||||||
|
end
|
||||||
|
|
||||||
|
def inspect
|
||||||
|
"<#{self.class}: @path=#{path}, @text=#{text.inspect}>"
|
||||||
end
|
end
|
||||||
|
|
||||||
def ==(other)
|
def ==(other)
|
||||||
|
@ -119,8 +119,9 @@ module Lrama
|
|||||||
|
|
||||||
VALID_TRACES = %w[
|
VALID_TRACES = %w[
|
||||||
none locations scan parse automaton bitsets
|
none locations scan parse automaton bitsets
|
||||||
closure grammar rules resource sets muscles tools
|
closure grammar rules actions resource
|
||||||
m4-early m4 skeleton time ielr cex all
|
sets muscles tools m4-early m4 skeleton time
|
||||||
|
ielr cex all
|
||||||
]
|
]
|
||||||
|
|
||||||
def validate_trace(trace)
|
def validate_trace(trace)
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -70,38 +70,16 @@ module Lrama
|
|||||||
reduce.look_ahead = look_ahead
|
reduce.look_ahead = look_ahead
|
||||||
end
|
end
|
||||||
|
|
||||||
# Returns array of [Shift, next_state]
|
|
||||||
def nterm_transitions
|
def nterm_transitions
|
||||||
return @nterm_transitions if @nterm_transitions
|
@nterm_transitions ||= transitions.select {|shift, _| shift.next_sym.nterm? }
|
||||||
|
|
||||||
@nterm_transitions = []
|
|
||||||
|
|
||||||
shifts.each do |shift|
|
|
||||||
next if shift.next_sym.term?
|
|
||||||
|
|
||||||
@nterm_transitions << [shift, @items_to_state[shift.next_items]]
|
|
||||||
end
|
end
|
||||||
|
|
||||||
@nterm_transitions
|
|
||||||
end
|
|
||||||
|
|
||||||
# Returns array of [Shift, next_state]
|
|
||||||
def term_transitions
|
def term_transitions
|
||||||
return @term_transitions if @term_transitions
|
@term_transitions ||= transitions.select {|shift, _| shift.next_sym.term? }
|
||||||
|
|
||||||
@term_transitions = []
|
|
||||||
|
|
||||||
shifts.each do |shift|
|
|
||||||
next if shift.next_sym.nterm?
|
|
||||||
|
|
||||||
@term_transitions << [shift, @items_to_state[shift.next_items]]
|
|
||||||
end
|
|
||||||
|
|
||||||
@term_transitions
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def transitions
|
def transitions
|
||||||
term_transitions + nterm_transitions
|
@transitions ||= shifts.map {|shift| [shift, @items_to_state[shift.next_items]] }
|
||||||
end
|
end
|
||||||
|
|
||||||
def selected_term_transitions
|
def selected_term_transitions
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
module Lrama
|
module Lrama
|
||||||
VERSION = "0.6.5".freeze
|
VERSION = "0.6.6".freeze
|
||||||
end
|
end
|
||||||
|
Loading…
x
Reference in New Issue
Block a user