Compare commits

...

2 commits

Author SHA1 Message Date
Gwenhael Le Moine
67632c6fb4
unit-test parser ruby spec/parser_spec.rb <-n test_parse_input_word> 2021-10-30 23:37:15 +02:00
Gwenhael Le Moine
9e91f407c2
split out parser 2021-10-30 23:36:49 +02:00
3 changed files with 115 additions and 28 deletions

62
lib/parser.rb Normal file
View 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
View file

@ -3,6 +3,8 @@
require 'readline'
require_relative "./lib/parser"
def run_REPL( stack )
Readline.completion_proc = proc do |s|
directory_list = Dir.glob("#{s}*")
@ -27,33 +29,6 @@ def run_REPL( stack )
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 )
parse_input( input ).each do |elt|
stack << elt
@ -64,7 +39,7 @@ end
def display_stack( stack )
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
end

50
spec/parser_spec.rb Normal file
View 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