Build NFA for each token pattern

This commit is contained in:
Josh Holtrop 2021-05-17 22:57:18 -04:00
parent cf8718b69c
commit 791340b292
3 changed files with 11 additions and 19 deletions

View File

@ -1,6 +1,7 @@
require_relative "imbecile/cli" require_relative "imbecile/cli"
require_relative "imbecile/grammar" require_relative "imbecile/grammar"
require_relative "imbecile/regex" require_relative "imbecile/regex"
require_relative "imbecile/regex/nfa"
require_relative "imbecile/regex/parser" require_relative "imbecile/regex/parser"
require_relative "imbecile/version" require_relative "imbecile/version"
require "erb" require "erb"

View File

@ -21,10 +21,10 @@ module Imbecile
@modulename = $1 @modulename = $1
elsif line =~ /^\s*class\s+(\S+)$/ elsif line =~ /^\s*class\s+(\S+)$/
@classname = $1 @classname = $1
elsif line =~ /^\s*token\s+(\S+)(?:\s+(.*))?$/ elsif line =~ /^\s*token\s+(\S+)(?:\s+(\S+))?$/
name, expr = $1, $2 name, pattern = $1, $2
if expr == "" if pattern.to_s == ""
expr = name pattern = name
end end
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}")
@ -32,15 +32,16 @@ module Imbecile
if @tokens[name] if @tokens[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] = expr @tokens[name] = {pattern: pattern}
else else
raise Error.new("Unexpected input on line #{line_number}: #{line}") raise Error.new("Unexpected input on line #{line_number}: #{line}")
end end
end end
# Build NFA from each token expression. # Build NFA from each token expression.
@tokens.transform_values! do |expr| @tokens.each do |token_name, token_def|
LexerNFA.new(expr) token_def[:regex] = Regex.new(token_def[:pattern])
token_def[:nfa] = token_def[:regex].parser.unit.to_nfa
end end
end end

View File

@ -1,20 +1,10 @@
module Imbecile module Imbecile
class Regex class Regex
class State attr_accessor :parser
attr_accessor :accepting
def initialize
@transitions = []
end
def add_transition(character_range, state)
@transitions << [character_range, state]
end
end
def initialize(pattern) def initialize(pattern)
parser = Parser.new(pattern) @parser = Parser.new(pattern)
end end
end end