From 9e91f407c27cbb20c47f77de62c2f5af48c0ed01 Mon Sep 17 00:00:00 2001 From: Gwenhael Le Moine Date: Sat, 30 Oct 2021 23:36:49 +0200 Subject: [PATCH] split out parser --- lib/parser.rb | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++ repl.rb | 31 +++----------------------- 2 files changed, 65 insertions(+), 28 deletions(-) create mode 100644 lib/parser.rb diff --git a/lib/parser.rb b/lib/parser.rb new file mode 100644 index 0000000..b6e09ed --- /dev/null +++ b/lib/parser.rb @@ -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 diff --git a/repl.rb b/repl.rb index 8d0e99e..9318a93 100644 --- a/repl.rb +++ b/repl.rb @@ -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