On Nov 14, 2011, at 10:23 PM, Trevor Daniels wrote:

> I'm trying to make a simple RPN calculator that reads in regular
> expressions from a file and evaluates them to execute code. Currently I
> have these regular expressions stored in an array of class objects that
> have 2 data objects (1. The regex itself and 2. The block of code that
> should be executed when a match is found). An example of one of the read
> in regex's is below:
> 
> [0-9]+
> lambda {|input| $myStack.push(input)}
> 
> Now, I get input from the user and compare that string to all the
> regular expressions in my array. When a match is found, the code is
> evaluated. So far it is working by entering in input one by one. Code
> and an example are below.
> 
> while input = gets
>  for i in 0..$regexArray.length-1
>    if ( input =~ Regexp.new($regexArray[i].regex) )
>      eval($regexArray[i].code).call(input)
>    end
>  end
> end
> 
> Example:
> 5
> 4
> +
> print
> 
> will give "9" as it should. However, I want to make it so I can enter
> input in one line like:
> 5 4 + print
> 
> I've tried matching the input string with the regex with: myMatch =
> regex.match(input)
> but when I enter a string such as "123 456" only the last part ("456")
> is matched when I need to first match the ("123"). Any help would be
> appreciated.

If your valid expressions contain no whitespace, you can split your input into individual tokens with split(/\s+/). As a minimal example, this works fine:


q = []
a = {
	/\d+/ => ->(input) { q << input.to_i },
	/\+|-/ => ->(op) { q.push(q.pop(2).reverse.reduce(op)) },
	/print/ => ->(match) { puts q.pop }
}

DATA.each_line do |input|
  input.split(/\s+/).each do |token|
    code = a[a.keys.detect { |k| token =~ k }]
    code.call(token) unless code.nil?
  end
end

__END__
5 4 + print
5 4 - print

Returns 9 and -1.

If you need to parse more complex input on each line, you should use StringScanner available in the standard library (require 'strscan').