Mini Parser

Hi all,

I have a requirement. I have a to read some commands from file and
output as another file. For example if the input file is like below:

6
WRITE Today
WRITE is
UNDO 1
WRITE my
UNDO 2
WRITE birthday

Output file will be like this.

Today is birthday

WRITE basically write’s string after the command and UNDO will undo N
number of line preceding it. Complexity here is last UNDO has to UNDO
the previous undo’s work.

So far I have been able to only come up with the below code:

begin
file = File.new(“abc.txt”, “r”)
while (line = file.gets)
line.grep(/WRITE/) { |s|
puts s
}
end
file.close

rescue => err
puts “Exception: #{err}”
err
end

Any help here?

On Wed, Sep 23, 2009 at 10:55 AM, Karthikeyan Balasubramanian
[email protected] wrote:

UNDO 2
So far I have been able to only come up with the below code:
rescue => err
puts “Exception: #{err}”
err
end

Any help here?

Posted via http://www.ruby-forum.com/.

If you want undoable commands you need to keep a command history. I’d
check out the Command design pattern if I were you.


Paul S.
http://www.nomadicfun.co.uk

[email protected]

Am Mittwoch 23 September 2009 11:55:24 schrieb Karthikeyan
Balasubramanian:

WRITE basically write’s string after the command and UNDO will undo N
number of line preceding it. Complexity here is last UNDO has to UNDO
the previous undo’s work.

Obviously you need to find out which WRITEs actually execute, before
producing
any output, since it’s hard to undo output that’s already been printed
to the
screen.

Since there are no conditional statements, you know that all the UNDOs
will
execute, so you can execute all the UNDOs in phase 1 and then execute
the
WRITEs that haven’t been UNDOne in PHASE 2.

The problem of UNDOing UNDOs can be solved by simply going through the
UNDOs
in reverse order.

This should work:

commands = File.readlines(sourcefile).map {|line|
line.chomp.split(/\s+/, 2)}

commands.reverse!
undos = 0
commands.reject! do |command, argument|
if undos > 0
undos -= 1
true
elsif command == “UNDO”
undos = argument.to_i
true
else
false
end
end
commands.reverse!

commands.each do |command, argument|
print argument, " "
end

This is exactly what I wanted.

Thank you a tons.