add runner and dictionary
This commit is contained in:
parent
94919db7a9
commit
ca315724ff
5 changed files with 72 additions and 34 deletions
24
lib/dictionary.rb
Normal file
24
lib/dictionary.rb
Normal file
|
@ -0,0 +1,24 @@
|
|||
# coding: utf-8
|
||||
|
||||
module Rpn
|
||||
class Dictionary
|
||||
def initialize
|
||||
@parser = Parser.new
|
||||
@words = {
|
||||
'+' => proc { |stack|
|
||||
stack + @parser.parse_input( (stack.pop[:value] + stack.pop[:value]).to_s )
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
def add( word )
|
||||
@words[ word[:name] ] = word[:value]
|
||||
end
|
||||
|
||||
def lookup( name )
|
||||
@words[ name ] if @words.include?( name )
|
||||
end
|
||||
|
||||
# TODO: alias
|
||||
end
|
||||
end
|
|
@ -19,6 +19,7 @@ module Rpn
|
|||
closed_programs = 0
|
||||
string_delimiters = 0
|
||||
regrouping = false
|
||||
|
||||
regrouped_input = []
|
||||
splitted_input.each do |elt|
|
||||
# TODO: handle buried-in-elt « and » (surround by ' ' and re-split)
|
||||
|
@ -64,15 +65,6 @@ module Rpn
|
|||
end
|
||||
end
|
||||
|
||||
if parsed_entry[:type] == :word
|
||||
if false
|
||||
# TODO: run word if known
|
||||
else
|
||||
parsed_entry[:type] = :name
|
||||
parsed_entry[:value] = "'#{parsed_entry[:value]}'" if parsed_entry[:value][0] != "'"
|
||||
end
|
||||
end
|
||||
|
||||
if parsed_entry[:type] == :numeric
|
||||
i = parsed_entry[:value].to_i
|
||||
f = parsed_entry[:value].to_f
|
||||
|
|
26
lib/runner.rb
Normal file
26
lib/runner.rb
Normal file
|
@ -0,0 +1,26 @@
|
|||
# coding: utf-8
|
||||
|
||||
module Rpn
|
||||
class Runner
|
||||
def initialize; end
|
||||
|
||||
def run_input( stack, dictionary, input )
|
||||
input.each do |elt|
|
||||
case elt[:type]
|
||||
when :word
|
||||
command = dictionary.lookup( elt[:value] )
|
||||
|
||||
if command.nil?
|
||||
stack << { type: :name, value: "'#{elt[:value]}'" }
|
||||
else
|
||||
stack = command.call( stack )
|
||||
end
|
||||
else
|
||||
stack << elt
|
||||
end
|
||||
end
|
||||
|
||||
[stack, dictionary]
|
||||
end
|
||||
end
|
||||
end
|
37
repl.rb
37
repl.rb
|
@ -1,15 +1,19 @@
|
|||
# coding: utf-8
|
||||
# frozen_string_literal: true
|
||||
|
||||
require "readline"
|
||||
require 'readline'
|
||||
|
||||
require "./lib/parser.rb"
|
||||
require './lib/dictionary'
|
||||
require './lib/parser'
|
||||
require './lib/runner'
|
||||
|
||||
module Rpn
|
||||
class Repl
|
||||
def initialize
|
||||
@parser = Parser.new
|
||||
@stack = []
|
||||
@dictionary = Dictionary.new
|
||||
@parser = Parser.new
|
||||
@runner = Runner.new
|
||||
end
|
||||
|
||||
def run
|
||||
|
@ -21,39 +25,24 @@ module Rpn
|
|||
Readline::HISTORY.grep(/^#{Regexp.escape(s)}/)
|
||||
end
|
||||
end
|
||||
Readline.completion_append_character = " "
|
||||
Readline.completion_append_character = ' '
|
||||
|
||||
loop do
|
||||
input = Readline.readline( " ", true )
|
||||
break if input.nil? || input == "exit"
|
||||
input = Readline.readline( ' ', true )
|
||||
break if input.nil? || input == 'exit'
|
||||
|
||||
# Remove blank lines from history
|
||||
Readline::HISTORY.pop if input.empty?
|
||||
|
||||
process_input( input )
|
||||
@stack, @dictionary = @runner.run_input( @stack, @dictionary,
|
||||
@parser.parse_input( input ) )
|
||||
|
||||
print_stack
|
||||
end
|
||||
end
|
||||
|
||||
def process_input( input )
|
||||
@parser.parse_input( input ).each do |elt|
|
||||
@stack << elt # TODO: (parse and) evaluate elt if needed
|
||||
end
|
||||
end
|
||||
|
||||
def format_element( elt )
|
||||
pp elt
|
||||
# case elt[:type]
|
||||
# when :program
|
||||
# "« #{elt[:value]} »"
|
||||
# when :string
|
||||
# "\"#{elt[:value]}\""
|
||||
# when :name
|
||||
# "'#{elt[:value]}'"
|
||||
# else
|
||||
elt[:value]
|
||||
# end
|
||||
elt[:value]
|
||||
end
|
||||
|
||||
def print_stack
|
||||
|
|
|
@ -13,7 +13,7 @@ class TestParser < Test::Unit::TestCase
|
|||
|
||||
def test_word
|
||||
result = Rpn::Parser.new.parse_input( 'dup' )
|
||||
assert_equal [{ value: "'dup'", type: :name }], result
|
||||
assert_equal [{ value: 'dup', type: :word }], result
|
||||
end
|
||||
|
||||
def test_string
|
||||
|
@ -63,6 +63,13 @@ class TestParser < Test::Unit::TestCase
|
|||
assert_equal [{ value: 2, type: :numeric }, { value: 3, type: :numeric }], result
|
||||
end
|
||||
|
||||
def test_number_number_word
|
||||
result = Rpn::Parser.new.parse_input( '2 3 +' )
|
||||
assert_equal [{ value: 2, type: :numeric },
|
||||
{ value: 3, type: :numeric },
|
||||
{ value: '+', type: :word }], result
|
||||
end
|
||||
|
||||
def test_number_string
|
||||
result = Rpn::Parser.new.parse_input( '4 "test"' )
|
||||
assert_equal [{ value: 4, type: :numeric }, { value: '"test"', type: :string }], result
|
||||
|
|
Loading…
Reference in a new issue