Move grammar parsing into new Grammar class

This commit is contained in:
josh committed 2022-06-05 10:23:34 -04:00
1 parent 34eb1370ff
commit 57a3e9d9f6
6 files changed
+113 -51

No files matched your search

+6 -44
View File
@@ -5,6 +5,7 @@ require_relative "propane/code_point_range"
require_relative "propane/fa"
require_relative "propane/fa/state"
require_relative "propane/fa/state/transition"
require_relative "propane/grammar"
require_relative "propane/lexer"
require_relative "propane/lexer/dfa"
require_relative "propane/parser"
@@ -36,12 +37,11 @@ class Propane
end
def initialize(input)
@tokens = {}
@rule_sets = {}
input = input.gsub("\r\n", "\n")
while !input.empty?
parse_grammar(input)
end
grammar = Grammar.new(input)
@classname = grammar.classname
@modulename = grammar.modulename
@tokens = grammar.tokens
@rule_sets = grammar.rule_sets
end
def generate(output_file, log_file)
@@ -58,44 +58,6 @@ class Propane
private
def parse_grammar(input)
if input.slice!(/\A\s+/)
# Skip white space.
elsif input.slice!(/\A#.*\n/)
# Skip comment lines.
elsif input.slice!(/\Amodule\s+(\S+)\n/)
@modulename = $1
elsif input.slice!(/\Aclass\s+(\S+)\n/)
@classname = $1
elsif input.slice!(/\Atoken\s+(\S+)(?:\s+(\S+))?\n/)
name, pattern = $1, $2
if pattern.nil?
pattern = name
end
unless name =~ /^[a-zA-Z_][a-zA-Z_0-9]*$/
raise Error.new("Invalid token name #{name}")
end
if @tokens[name]
raise Error.new("Duplicate token name #{name}")
else
@tokens[name] = Token.new(name, pattern, @tokens.size)
end
elsif input.slice!(/\Adrop\s+(\S+)\n/)
pattern = $1
@tokens[name] = Token.new(nil, pattern, @tokens.size)
elsif input.slice!(/\A(\S+)\s*:\s*\[(.*?)\] <<\n(.*?)^>>\n/m)
rule_name, components, code = $1, $2, $3
components = components.strip.split(/\s+/)
@rule_sets[rule_name] ||= RuleSet.new(rule_name, @rule_sets.size)
@rule_sets[rule_name].add_rule(components, code)
else
if input.size > 25
input = input.slice(0..20) + "..."
end
raise Error.new("Unexpected grammar input: #{input}")
end
end
def expand_rules
@rule_sets.each do |rule_name, rule_set|
if @tokens.include?(rule_name)