Skip to content
This repository has been archived by the owner on May 13, 2019. It is now read-only.

Commit

Permalink
Select Case; untested Do/Loop variants.
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewd committed Nov 21, 2010
1 parent 8d2aa4b commit c4ebc62
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 26 deletions.
6 changes: 6 additions & 0 deletions lib/rasp/ast.rb
Expand Up @@ -25,6 +25,12 @@ def self.binary_op(klass, lhs, ary, op_attr=nil, attr=:rhs)
lhs
end

def self.list(lhs, ary, attr=:rhs)
[lhs] + ary.matches.map do |curr|
curr.send(attr).value
end
end

class Node
def graph
Rubinius::AST::AsciiGrapher.new(self, Node).print
Expand Down
2 changes: 1 addition & 1 deletion lib/rasp/ast/call.rb
Expand Up @@ -39,7 +39,7 @@ def bytecode(g)
g.send :"vb:#@name", 0
end
else
if @args.nil? || @args.empty?
if @args.nil?
if g.constants.key?(@name)
g.push_literal g.constants[@name]
return
Expand Down
6 changes: 3 additions & 3 deletions lib/rasp/ast/flow.rb
Expand Up @@ -34,7 +34,7 @@ def bytecode(g)

@condition.bytecode(g)
g.meta_push_0
g.meta_send_op_eq
g.meta_send_op_equal g.find_literal(:==)
g.giz done

@body.each do |s|
Expand Down Expand Up @@ -248,7 +248,7 @@ def initialize(expr, cases, else_body)
end

def bytecode(g)
done = new_label
done = g.new_label
@expr.bytecode(g)
@cases.each do |c|
c.bytecode(g, done)
Expand Down Expand Up @@ -284,7 +284,7 @@ def bytecode(g, done)
matches.each do |m|
g.dup
m.bytecode(g)
g.meta_send_op_eq find_literal(:==)
g.meta_send_op_equal g.find_literal(:==)
if m == matches.last
g.giz failed_match
else
Expand Down
11 changes: 7 additions & 4 deletions lib/rasp/compiler.rb
@@ -1,6 +1,13 @@
# Stolen from poison; original code Copyright (c) 2010 Brian Ford.
module Rasp
class Code
def vb_rnd
Kernel.rand
end

instance_methods.each do |m|
alias_method m.to_s.sub(/^vb_/, 'vb:').intern, m if m.to_s =~ /^vb_/
end
end
class Function < Code
attr_accessor :name
Expand Down Expand Up @@ -120,13 +127,9 @@ def compile_function(ast, filename="(function)", line_number=1)
gg.local_count = ast.local_count
gg.local_names = ast.local_names

p :compile_function
gg.encode
p :compile_function
cm = gg.package ::Rubinius::CompiledMethod
p :compile_function
puts cm.decode if $DEBUG
p :compile_function

code = Rasp::Function.new
code.name = ast.name
Expand Down
46 changes: 28 additions & 18 deletions lib/rasp/parser.citrus
Expand Up @@ -69,19 +69,30 @@ grammar Rasp::Parser
`with` SP expression ENDSTATEMENT statement* `end` SP `with` ENDSTATEMENT
end
rule select_block
`select` SP `case` SP expression ENDSTATEMENT
(`case` SP expression_list ENDSTATEMENT statement*)+
(`case` SP `else` statement*)?
`end` SP `select` ENDSTATEMENT
(
init:(`select` SP `case` SP expression ENDSTATEMENT)
{ expression.value }
cases:(
(`case` SP expression_list ENDSTATEMENT body:statement*)
)+
elsepart:(
(`case` SP `else` elsebody:statement*)
{ elsebody.matches.map {|m| m.value }.compact }
)?
`end` SP `select` ENDSTATEMENT
) {
c = cases.matches.map {|m| Rasp::AST::Case.new(m.expression_list.value, m.body.matches.map {|x| x.value }.compact) }
Rasp::AST::SelectCase.new(init.value, c, elsepart.matches.first.value)
}
end
rule for_each
`for` SP `each` SP identifier SP `in` SP expression ENDSTATEMENT statement* `next` ENDSTATEMENT
end
rule do_loop
((`do` ENDSTATEMENT body:statement* `loop` ENDSTATEMENT) { Rasp::AST::Loop.new :do, body.matches.map {|m| m.value }.compact }
|`do` SP (`while` | `until`) SP expression ENDSTATEMENT statement* `loop` ENDSTATEMENT
|`do` ENDSTATEMENT statement* `loop` SP (`while` | `until`) SP expression ENDSTATEMENT
|`while` SP expression ENDSTATEMENT statement* `wend` ENDSTATEMENT
|(`do` SP flip:(`while` | `until`) SP expression ENDSTATEMENT body:statement* `loop` ENDSTATEMENT) { Rasp::AST::DoWhile.new :do, expression.value, flip == 'until', body.matches.map {|m| m.value }.compact }
|(`do` ENDSTATEMENT body:statement* `loop` SP flip:(`while` | `until`) SP expression ENDSTATEMENT) { Rasp::AST::LoopWhile.new :do, expression.value, flip == 'until', body.matches.map {|m| m.value }.compact }
|(`while` SP expression ENDSTATEMENT body:statement* `wend` ENDSTATEMENT) { Rasp::AST::DoWhile.new :do, expression.value, false, body.matches.map {|m| m.value }.compact }
)
end
rule for_next
Expand Down Expand Up @@ -113,21 +124,19 @@ grammar Rasp::Parser
) {
e = elsechunk.matches.first
e &&= e.elsebody.matches.map {|m| m.value }.compact
p e
ls = mids.matches.map {|m| m.value }
p ls
while x = ls.pop
x.false_body = e
e = [x]
end
v = orig.value
v.false_body = e
p v
v
}
end
rule simple_statement_chain
(list:(lhs:simple_statement SP? ":" SP?)* rhs:simple_statement) { (first(:list) ? list.map {|x| x.lhs.value } : []) + [rhs.value] }
(lhs:simple_statement list:(SP? "::" SP? rhs:simple_statement
)*) { Rasp::AST.list(lhs, list) }
end
rule simple_statement
(assignment
Expand Down Expand Up @@ -182,14 +191,14 @@ grammar Rasp::Parser
}
end
rule objvalue
(init:((local:identifier | "." withprop:identifier) ("(" SP? (expression_list SP?)? ")")?)
(init:((local:identifier | "." withprop:identifier) (paren:"(" SP? (expression_list SP?)? ")")?)
{ Rasp::AST::GetCall.new(first(:withprop) ? Rasp::AST::WithRef.new : nil,
(first(:local) || first(:withprop)).value,
find(:expression_list).first && find(:expression_list).first.value) }
list:("." identifier ("(" SP? (expression_list SP?)? ")")?)*)
find(:paren).empty? ? nil : (find(:expression_list).first && find(:expression_list).first.value || [])) }
list:("." identifier (paren:"(" SP? (expression_list SP?)? ")")?)*)
{
list.matches.inject(init.value) do |full, x|
Rasp::AST::GetCall.new(full, x.identifier.value, x.first(:expression_list) && x.first(:expression_list).value)
Rasp::AST::GetCall.new(full, x.identifier.value, find(:paren).empty? ? nil : (x.first(:expression_list) && x.first(:expression_list).value || []))
end
}
end
Expand Down Expand Up @@ -282,8 +291,8 @@ grammar Rasp::Parser
)*) { Rasp::AST.math_op(self) }
end
rule unary_expr
("+" SP? value_expr { Rasp::AST::UnaryPlus.new value_expr }
|"-" SP? value_expr { Rasp::AST::UnaryMinus.new value_expr }
(("+" SP? value_expr) { Rasp::AST::UnaryPlus.new(value_expr.value) }
|("-" SP? value_expr) { Rasp::AST::UnaryMinus.new(value_expr.value) }
|value_expr
)
end
Expand Down Expand Up @@ -318,7 +327,8 @@ grammar Rasp::Parser
/[ \t]*(?::|(?:'[^\n]+)?\n)[ \t]*/ { nil }
end
rule expression_list
(list:(lhs:expression SP? "," SP?)* rhs:expression) { (first(:list) ? list.map {|x| x.lhs.value } : []) + [rhs.value] }
(lhs:expression list:(SP? "," SP? rhs:expression
)*) { Rasp::AST.list(lhs, list) }
end


Expand Down
11 changes: 11 additions & 0 deletions t/samples/selcase.vbs
@@ -0,0 +1,11 @@

Dim x: x = 21
Select Case x - 4
Case 1, 2, 3
WScript.Echo "Low"
Case 16, 17
Wscript.Echo "Hexage"
Case Else
wscript.echo "Other"
End Select

0 comments on commit c4ebc62

Please sign in to comment.