Skip to content

Instantly share code, notes, and snippets.

@diiq
Created January 24, 2016 17:31
Show Gist options
  • Save diiq/10ac884e49ae6aacf843 to your computer and use it in GitHub Desktop.
Save diiq/10ac884e49ae6aacf843 to your computer and use it in GitHub Desktop.
require "rsec"
module Parsing
extend Rsec::Helpers
# build the parser
def self.query_lang
# Predicate should be constructed with loop over keywords
predicate = /.*?(?=STATUS IS|TYPE IS|AND|OR|\(|\)|$)/.r.map { |s| s.strip }
# write a helper method to add new statement types
status_statement = (symbol('STATUS IS') >> predicate).map { |s| {status: s} }
type_statement = (symbol('TYPE IS') >> predicate).map { |s| {type: s} }
# statement should loop over all statement types
statement = status_statement | type_statement
# Once this part is settled, it shouldn't need to change. Hardest
# part: building a query for TASK THING OR (TASK THING AND TASK
# THING)
parenthetical = ('('.r >> lazy { expr } << ')')
unit = statement | parenthetical
and_ = symbol('AND').map { {} } # cheating, won't work forever
anded = unit.join(and_).map { |s| s.reduce(&:merge) }
expr = anded.join(symbol('OR'))
expr.eof
end
def self.parse str
query_lang.parse! str
end
end
p Parsing::parse 'STATUS IS hi'
p Parsing::parse 'STATUS IS hi AND TYPE IS good bye'
p Parsing::parse 'STATUS IS sweet OR (TYPE IS sweet AND STATUS IS super sweet)'
p Parsing::parse 'STATUS IS sweet OR ((STATUS IS super sweet AND TYPE IS rockin) OR TYPE IS sweet)'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment