Expand rules
This commit is contained in:
parent
3f92ae46c4
commit
6ce94e15af
@ -7,6 +7,7 @@ require_relative "imbecile/fa/state"
|
|||||||
require_relative "imbecile/fa/state/transition"
|
require_relative "imbecile/fa/state/transition"
|
||||||
require_relative "imbecile/lexer"
|
require_relative "imbecile/lexer"
|
||||||
require_relative "imbecile/lexer/dfa"
|
require_relative "imbecile/lexer/dfa"
|
||||||
|
require_relative "imbecile/parser"
|
||||||
require_relative "imbecile/regex"
|
require_relative "imbecile/regex"
|
||||||
require_relative "imbecile/regex/nfa"
|
require_relative "imbecile/regex/nfa"
|
||||||
require_relative "imbecile/regex/unit"
|
require_relative "imbecile/regex/unit"
|
||||||
@ -41,34 +42,9 @@ class Imbecile
|
|||||||
end
|
end
|
||||||
|
|
||||||
def generate(output_file, log_file)
|
def generate(output_file, log_file)
|
||||||
token_names = @tokens.each_with_object({}) do |token, token_names|
|
expand_rules
|
||||||
if token_names.include?(token.name)
|
|
||||||
raise Error.new("Duplicate token name #{token.name}")
|
|
||||||
end
|
|
||||||
token_names[token.name] = token
|
|
||||||
end
|
|
||||||
rule_names = @rules.each_with_object({}) do |rule, rule_names|
|
|
||||||
if token_names.include?(rule.name)
|
|
||||||
raise Error.new("Rule name collides with token name #{rule.name}")
|
|
||||||
end
|
|
||||||
rule_names[rule.name] ||= []
|
|
||||||
rule_names[rule.name] << rule
|
|
||||||
end
|
|
||||||
unless rule_names["Start"]
|
|
||||||
raise Error.new("Start rule not found")
|
|
||||||
end
|
|
||||||
@rules.each do |rule|
|
|
||||||
rule.components.map! do |component|
|
|
||||||
if token_names[component]
|
|
||||||
token_names[component]
|
|
||||||
elsif rule_names[component]
|
|
||||||
rule_names[component]
|
|
||||||
else
|
|
||||||
raise Error.new("Symbol #{component} not found")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
lexer = Lexer.new(@tokens)
|
lexer = Lexer.new(@tokens)
|
||||||
|
parser = Parser.new(@tokens, @rules)
|
||||||
classname = @classname || File.basename(output_file).sub(%r{[^a-zA-Z0-9].*}, "").capitalize
|
classname = @classname || File.basename(output_file).sub(%r{[^a-zA-Z0-9].*}, "").capitalize
|
||||||
erb = ERB.new(File.read(File.join(File.dirname(File.expand_path(__FILE__)), "../assets/parser.d.erb")), nil, "<>")
|
erb = ERB.new(File.read(File.join(File.dirname(File.expand_path(__FILE__)), "../assets/parser.d.erb")), nil, "<>")
|
||||||
result = erb.result(binding.clone)
|
result = erb.result(binding.clone)
|
||||||
@ -112,6 +88,54 @@ class Imbecile
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def expand_rules
|
||||||
|
token_names = @tokens.each_with_object({}) do |token, token_names|
|
||||||
|
if token_names.include?(token.name)
|
||||||
|
raise Error.new("Duplicate token name #{token.name}")
|
||||||
|
end
|
||||||
|
token_names[token.name] = token
|
||||||
|
end
|
||||||
|
rule_names = @rules.each_with_object({}) do |rule, rule_names|
|
||||||
|
if token_names.include?(rule.name)
|
||||||
|
raise Error.new("Rule name collides with token name #{rule.name}")
|
||||||
|
end
|
||||||
|
rule_names[rule.name] ||= []
|
||||||
|
rule_names[rule.name] << rule
|
||||||
|
end
|
||||||
|
unless rule_names["Start"]
|
||||||
|
raise Error.new("Start rule not found")
|
||||||
|
end
|
||||||
|
@rules.each do |rule|
|
||||||
|
rule.components.map! do |component|
|
||||||
|
if token_names[component]
|
||||||
|
token_names[component]
|
||||||
|
elsif rule_names[component]
|
||||||
|
rule_names[component]
|
||||||
|
else
|
||||||
|
raise Error.new("Symbol #{component} not found")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
new_rules = []
|
||||||
|
begin
|
||||||
|
@rules += new_rules
|
||||||
|
new_rules = []
|
||||||
|
@rules.delete_if do |rule|
|
||||||
|
replaced = false
|
||||||
|
rule.components.each_with_index do |component, index|
|
||||||
|
if component.is_a?(Array)
|
||||||
|
component.each do |new_component|
|
||||||
|
new_components = rule.components[0, index] + [new_component] + rule.components[index + 1, rule.components.size]
|
||||||
|
new_rules << Rule.new(rule.name, new_components, rule.code)
|
||||||
|
end
|
||||||
|
replaced = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
replaced
|
||||||
|
end
|
||||||
|
end while new_rules.size > 0
|
||||||
|
end
|
||||||
|
|
||||||
class << self
|
class << self
|
||||||
|
|
||||||
def run(input_file, output_file, log_file)
|
def run(input_file, output_file, log_file)
|
||||||
|
10
lib/imbecile/parser.rb
Normal file
10
lib/imbecile/parser.rb
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
class Imbecile
|
||||||
|
|
||||||
|
class Parser
|
||||||
|
|
||||||
|
def initialize(tokens, rules)
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
Loading…
x
Reference in New Issue
Block a user