Skip to content

Instantly share code, notes, and snippets.

@baroquebobcat
Created August 11, 2013 18:23
Show Gist options
  • Select an option

  • Save baroquebobcat/6206204 to your computer and use it in GitHub Desktop.

Select an option

Save baroquebobcat/6206204 to your computer and use it in GitHub Desktop.
class Transform < Parslet::Transform
rule(:integer => simple(:int)) { AST::IntLiteral.new int }
rule(:args => simple(:arg)) { AST::SelectArgs.new [arg] }
rule(:args => sequence(:args)) { AST::SelectArgs.new args }
rule(:integer_argument => simple(:int)) { AST::IntArgument.new int}
rule(:column_argument => simple(:name)) { AST::ColumnArgument.new name}
rule(:select => simple(:select),
:args => simple(:args),
:table_name => simple(:from) ) { AST::FromSelect.new args, from}
rule(:select => simple(:select),
:args => simple(:args)) { AST::Select.new args}
rule(:wildcard => simple(:wildcard)) { AST::Wildcard.new }
end
module AST
class IntLiteral < Struct.new(:int)
def eval; int.to_i; end
end
class Wildcard < Struct.new(:int)
def eval table
table.map { |row| row }
end
end
class SelectArgs < Struct.new(:args)
def eval table
table.map do |row|
Hash[
args.map { |arg| [arg.name, arg.eval(row)] }
]
end
end
end
class IntArgument < Struct.new(:int)
def name
int.eval.to_s # :/
end
def eval row
int.eval
end
end
class ColumnArgument < Struct.new(:column_name)
def name
column_name.to_s
end
def eval row
row[name]
end
end
class FromSelect < Struct.new(:args, :table_name)
def eval database
table = database[table_name.to_sym]
args.eval table
end
end
class Select < Struct.new(:args)
def eval table
args.eval [{}]
end
end
end
class Walker < HandWavyVisitor
visit :select, [:args, :from] do |args, from|
rows = visit from
visit args, rows
end
visit :select, [] do |args, from|
visit args, [{}]
end
visit :wildcard, [] do |rows|
rows.map { |row| row }
end
visit :column_argument, [:ident] do |column_name, row|
row[column_name]
end
visit :arguments, [:argument_list] do |args, rows|
rows.map do |row|
Hash[
args.map { |arg| [arg.to_s, visit(arg, row)] }
]
end
end
visit :integer do |int_string|
Integer(int_string)
end
visit :from, [:table_name] do |table_name, database|
database[table_name.to_sym]
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment