Skip to content

Instantly share code, notes, and snippets.

@Sutto
Created May 1, 2011 12:26
Show Gist options
  • Save Sutto/950470 to your computer and use it in GitHub Desktop.
Save Sutto/950470 to your computer and use it in GitHub Desktop.
require 'parslet'
module SmegHead
module ACL
class Parser < Parslet::Parser
def self.parse(text)
parser = new
parser.parse text
rescue Parslet::ParseFailed => error
puts error, parser.root.error_tree
end
def collection_of(type, max = 5)
type >> (comma_seperator >> type).repeat(0, max)
end
rule(:space) { (str(' ') | str(' ')) }
rule(:spaces?) { space.repeat }
rule(:spaces) { space.repeat 1 }
rule(:comma_seperator) { str(',') >> spaces }
rule(:wildcard) { str('*') }
rule(:alphanumeric) { match['A-Za-z0-9'] }
rule(:characters) { alphanumeric | match['\-\_'] }
rule(:ref_part) { alphanumeric >> characters.repeat }
rule(:ref_suffix) { str('/').maybe >> characters.repeat >> wildcard }
rule(:ref_name) { ref_part >> (str('/') >> ref_part).repeat }
rule(:target_type) { str('branch') | str('tag') | str('refs') }
rule(:target_matcher) { wildcard | (wildcard.maybe >> ref_name >> ref_suffix.maybe) }
rule(:specific_target) { target_type.as(:type) >> spaces >> target_matcher.as(:matcher) }
rule(:aot_target) { str('all').as(:all) >> spaces >> target_type.as(:type) >> str('s').maybe }
rule(:target) { specific_target | aot_target }
rule(:actor_type) { str('user') | str('group') }
rule(:specific_actor) { actor_type.as(:type) >> spaces >> (alphanumeric >> characters.repeat).as(:name) }
rule(:aot_actors) { str('collaborators').as(:type) | (str('all').as(:all) >> spaces >> actor_type.as(:type) >> str('s')) }
rule(:actor) { aot_actors | specific_actor }
rule(:action) { str('push') | str('pull') | str('destroy') | str('create') | str('all') }
rule(:verb) { (str('allow') | str('deny')) }
rule(:newline) { str("\n") >> str("\r").maybe }
rule(:expression) do
collection_of(verb).as(:verbs) >>
spaces >>
collection_of(action).as(:actions) >>
spaces >> str('from') >> spaces >>
collection_of(actor).as(:actors) >>
spaces >> str('to') >> spaces >>
collection_of(target).as(:target)
end
rule(:line) { spaces? >> expression >> spaces? }
rule(:lines) { (line >> newline).repeat >> line >> newline.maybe }
root :lines
end
end
end
require 'rubygems'
require 'acl_parser'
require 'ap'
example_acl_list = <<-END
allow destroy from user Sutto to branch feature/*
allow push from user Sutto to branch master
END
puts 'No trailing white space:'
ap SmegHead::ACL::Parser.parse(example_acl_list.strip)
puts "\n\n"
puts 'Trailing white space:'
ap SmegHead::ACL::Parser.parse(example_acl_list)
puts "\n\n"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment