Compare commits
2 commits
da2bd5241c
...
67632c6fb4
Author | SHA1 | Date | |
---|---|---|---|
|
67632c6fb4 | ||
|
9e91f407c2 |
3 changed files with 115 additions and 28 deletions
62
lib/parser.rb
Normal file
62
lib/parser.rb
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
# coding: utf-8
|
||||||
|
|
||||||
|
class String
|
||||||
|
def numeric?
|
||||||
|
Float(self) != nil rescue false
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def parse_input( input )
|
||||||
|
splitted_input = input.split(' ')
|
||||||
|
parsed_tree = []
|
||||||
|
|
||||||
|
regrouping = false
|
||||||
|
splitted_input.each do |elt|
|
||||||
|
next if elt.length == 1 && elt[0] == '»'
|
||||||
|
|
||||||
|
parsed_entry = { 'value' => elt }
|
||||||
|
|
||||||
|
if regrouping
|
||||||
|
parsed_entry = parsed_tree.pop
|
||||||
|
|
||||||
|
parsed_entry['value'] = "#{parsed_entry['value']} #{elt}".strip
|
||||||
|
else
|
||||||
|
parsed_entry['type'] = case elt[0]
|
||||||
|
when '«'
|
||||||
|
'PROGRAM'
|
||||||
|
when '"'
|
||||||
|
'STRING'
|
||||||
|
when '\''
|
||||||
|
'NAME'
|
||||||
|
else
|
||||||
|
if elt.numeric?
|
||||||
|
'NUMBER'
|
||||||
|
else
|
||||||
|
'WORD' # TODO: if word isn't known then it's a NAME
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
parsed_entry['value'] = elt[1..] if %W[PROGRAM STRING NAME].include?( parsed_entry['type'] )
|
||||||
|
end
|
||||||
|
|
||||||
|
regrouping = ( (parsed_entry['type'] == 'NAME' && elt[-1] != '\'') ||
|
||||||
|
(parsed_entry['type'] == 'STRING' && elt[-1] != '"') ||
|
||||||
|
(parsed_entry['type'] == 'PROGRAM' && elt[-1] != '»') )
|
||||||
|
|
||||||
|
parsed_entry['value'] = if ( (parsed_entry['type'] == 'NAME' && elt[-1] == '\'') ||
|
||||||
|
(parsed_entry['type'] == 'STRING' && elt[-1] == '"') ||
|
||||||
|
(parsed_entry['type'] == 'PROGRAM' && elt[-1] == '»') )
|
||||||
|
(parsed_entry['value'][..-2]).strip
|
||||||
|
elsif parsed_entry['type'] == 'NUMBER'
|
||||||
|
parsed_entry['value'].to_f
|
||||||
|
elsif parsed_entry['type'] == 'WORD'
|
||||||
|
parsed_entry['value']
|
||||||
|
else
|
||||||
|
parsed_entry['value']
|
||||||
|
end
|
||||||
|
|
||||||
|
parsed_tree << parsed_entry
|
||||||
|
end
|
||||||
|
|
||||||
|
parsed_tree
|
||||||
|
end
|
31
repl.rb
31
repl.rb
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
require 'readline'
|
require 'readline'
|
||||||
|
|
||||||
|
require_relative "./lib/parser"
|
||||||
|
|
||||||
def run_REPL( stack )
|
def run_REPL( stack )
|
||||||
Readline.completion_proc = proc do |s|
|
Readline.completion_proc = proc do |s|
|
||||||
directory_list = Dir.glob("#{s}*")
|
directory_list = Dir.glob("#{s}*")
|
||||||
|
@ -27,33 +29,6 @@ def run_REPL( stack )
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def parse_input( input )
|
|
||||||
splitted_input = input.split( " " )
|
|
||||||
parsed_input = []
|
|
||||||
|
|
||||||
regrouping = false
|
|
||||||
splitted_input.each do |elt|
|
|
||||||
if regrouping
|
|
||||||
partial_elt = parsed_input.pop
|
|
||||||
elt = "#{partial_elt} #{elt}"
|
|
||||||
end
|
|
||||||
|
|
||||||
if regrouping
|
|
||||||
regrouping = false if (elt[0] == '\'' and elt[-1] == '\'') or (elt[0] == '"' and elt[-1] == '"') or (elt[0] == '«' and elt[-1] == '»')
|
|
||||||
else
|
|
||||||
regrouping = true if elt[0] == '\'' or elt[0] == '"' or elt[0] == '«'
|
|
||||||
end
|
|
||||||
|
|
||||||
# 'xx' is a name (no space allowed)
|
|
||||||
# "xx x x xx" is a string
|
|
||||||
# « xx xx xx » is a program (must have inner spaces)
|
|
||||||
|
|
||||||
parsed_input << elt
|
|
||||||
end
|
|
||||||
|
|
||||||
parsed_input
|
|
||||||
end
|
|
||||||
|
|
||||||
def process_input( stack, input )
|
def process_input( stack, input )
|
||||||
parse_input( input ).each do |elt|
|
parse_input( input ).each do |elt|
|
||||||
stack << elt
|
stack << elt
|
||||||
|
@ -64,7 +39,7 @@ end
|
||||||
|
|
||||||
def display_stack( stack )
|
def display_stack( stack )
|
||||||
stack_size = stack.size
|
stack_size = stack.size
|
||||||
stack.each_with_index { |v, i| puts "#{stack_size - i}: #{v}"}
|
stack.each_with_index { |elt, i| puts "#{stack_size - i}: #{elt['value']}"}
|
||||||
|
|
||||||
stack
|
stack
|
||||||
end
|
end
|
||||||
|
|
50
spec/parser_spec.rb
Normal file
50
spec/parser_spec.rb
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
# coding: utf-8
|
||||||
|
require_relative "../lib/parser"
|
||||||
|
|
||||||
|
require 'test/unit'
|
||||||
|
|
||||||
|
class TestParser < Test::Unit::TestCase
|
||||||
|
def test_parse_input_number
|
||||||
|
result = parse_input( "1" )
|
||||||
|
assert_equal [ { 'value' => 1, 'type' => 'NUMBER' } ], result
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_parse_input_word
|
||||||
|
result = parse_input( "dup" )
|
||||||
|
assert_equal [ { 'value' => "dup", 'type' => 'WORD' } ], result
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_parse_input_string
|
||||||
|
result = parse_input( "\"test\"" )
|
||||||
|
assert_equal [ { 'value' => "test", 'type' => 'STRING' } ], result
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_parse_input_name
|
||||||
|
result = parse_input( "'test'" )
|
||||||
|
assert_equal [ { 'value' => "test", 'type' => 'NAME' } ], result
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_parse_input_program
|
||||||
|
result = parse_input( "« test »" )
|
||||||
|
assert_equal [ { 'value' => "test", 'type' => 'PROGRAM' } ], result
|
||||||
|
|
||||||
|
result = parse_input( "«test »" )
|
||||||
|
assert_equal [ { 'value' => "test", 'type' => 'PROGRAM' } ], result
|
||||||
|
|
||||||
|
result = parse_input( "« test test »" )
|
||||||
|
assert_equal [ { 'value' => "test test", 'type' => 'PROGRAM' } ], result
|
||||||
|
|
||||||
|
result = parse_input( "« test \"test\" test »" )
|
||||||
|
assert_equal [ { 'value' => "test \"test\" test", 'type' => 'PROGRAM' } ], result
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_parse_input_number_number
|
||||||
|
result = parse_input( "2 3" )
|
||||||
|
assert_equal [ { 'value' => 2, 'type' => 'NUMBER' }, { 'value' => 3, 'type' => 'NUMBER' } ], result
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_parse_input_number_string
|
||||||
|
result = parse_input( "4 \"test\"" )
|
||||||
|
assert_equal [ { 'value' => 4, 'type' => 'NUMBER' }, { 'value' => "test", 'type' => 'STRING' } ], result
|
||||||
|
end
|
||||||
|
end
|
Loading…
Reference in a new issue