Skip to content

Instantly share code, notes, and snippets.

@franckverrot
Forked from anonymous/balanced_parens.rb
Created December 15, 2012 07:33
Show Gist options
  • Save franckverrot/4291939 to your computer and use it in GitHub Desktop.
Save franckverrot/4291939 to your computer and use it in GitHub Desktop.
require "./tinyparse"
parser = Tinyparse.build do
paren "(", :main, ")", :main
main [:paren, ""]
end
["((()))", "(((", "()()((()()))", "))(("].each do |str|
puts str
if parser =~ str
puts " \e[32;1mis valid\e[0m"
else
puts " \e[31;1mis invalid\e[0m"
end
end
class Tinyparse
def self.build(&bk)
new.tap { |t| t.instance_eval(&bk) }.to_regexp
end
attr_reader :rules
def initialize
@rules = {}
end
def to_regexp
Regexp.new("\\A" << @rules.map { |name,re| "(?<#{name}>#{re}){0}" }.join << "\\g<main>\\z")
end
def method_missing(rule, *args)
compile = ->x {
case x
when Regexp
Regexp.union(//, x).source["(?-mix:)|".length..-1]
when String
Regexp.escape(x)
when Symbol
"\\g<#{x}>"
when Array
"(#{x.map(&compile).join("|")})"
end
}
@rules[rule] = args.map(&compile).join
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment