Add Grammar::Token class

This commit is contained in:
Josh Holtrop 2021-06-06 14:04:33 -04:00
parent 03b2e87186
commit afea886ecb
3 changed files with 47 additions and 10 deletions

View File

@ -3,6 +3,7 @@ require "set"
require_relative "imbecile/cli" require_relative "imbecile/cli"
require_relative "imbecile/code_point_range" require_relative "imbecile/code_point_range"
require_relative "imbecile/grammar" require_relative "imbecile/grammar"
require_relative "imbecile/grammar/token"
require_relative "imbecile/regex" require_relative "imbecile/regex"
require_relative "imbecile/regex/fa" require_relative "imbecile/regex/fa"
require_relative "imbecile/regex/fa/state" require_relative "imbecile/regex/fa/state"

View File

@ -1,15 +1,21 @@
module Imbecile module Imbecile
class Grammar class Grammar
# @return [String, nil] Module name. # @return [String, nil]
# Module name.
attr_reader :modulename attr_reader :modulename
# @return [String, nil] Class name. # @return [String, nil]
# Class name.
attr_reader :classname attr_reader :classname
# @return [Array<Token>]
# Tokens.
attr_reader :tokens
def initialize(input) def initialize(input)
@tokens = {} @tokens = []
@rules = {} token_names = Set.new
input.each_line.each_with_index do |line, line_index| input.each_line.each_with_index do |line, line_index|
line = line.chomp line = line.chomp
line_number = line_index + 1 line_number = line_index + 1
@ -29,10 +35,11 @@ module Imbecile
unless name =~ /^[a-zA-Z_][a-zA-Z_0-9]*$/ unless name =~ /^[a-zA-Z_][a-zA-Z_0-9]*$/
raise Error.new("Invalid token name #{name} on line #{line_number}") raise Error.new("Invalid token name #{name} on line #{line_number}")
end end
if @tokens[name] if token_names.include?(name)
raise Error.new("Duplicate token name #{name} on line #{line_number}") raise Error.new("Duplicate token name #{name} on line #{line_number}")
end end
@tokens[name] = {pattern: pattern} @tokens << Token.new(name, pattern, @tokens.size)
token_names << name
else else
raise Error.new("Unexpected input on line #{line_number}: #{line}") raise Error.new("Unexpected input on line #{line_number}: #{line}")
end end
@ -40,12 +47,14 @@ module Imbecile
# Build NFA from each token expression. # Build NFA from each token expression.
i = 0 i = 0
@tokens.each do |token_name, token_def| nfas = @tokens.map do |token|
token_def[:regex] = Regex.new(token_def[:pattern]) regex = Regex.new(token.pattern)
token_def[:regex].nfa.end_state.accepts = "#{i}:#{token_name}" regex.nfa.end_state.accepts = "#{i}:#{token.name}"
puts regex.nfa
i += 1 i += 1
regex.nfa
end end
dfa = Regex::DFA.new(@tokens.map {|token_name, token_def| token_def[:regex].nfa}) dfa = Regex::DFA.new(nfas)
puts dfa puts dfa
end end

View File

@ -0,0 +1,27 @@
module Imbecile
class Grammar
class Token
# @return [String]
# Token name.
attr_reader :name
# @return [String]
# Token pattern.
attr_reader :pattern
# @return [Integer]
# Token ID.
attr_reader :id
def initialize(name, pattern, id)
@name = name
@pattern = pattern
@id = id
end
end
end
end