2021-10-30 23:36:49 +02:00
|
|
|
# coding: utf-8
|
|
|
|
|
2021-11-23 13:10:03 +01:00
|
|
|
module Rpl
|
2021-11-09 16:50:01 +01:00
|
|
|
class Parser
|
|
|
|
def initialize; end
|
2021-10-30 23:36:49 +02:00
|
|
|
|
2021-11-09 16:50:01 +01:00
|
|
|
def numeric?( elt )
|
|
|
|
!Float(elt).nil?
|
|
|
|
rescue ArgumentError
|
|
|
|
false
|
2021-10-30 23:36:49 +02:00
|
|
|
end
|
|
|
|
|
2021-11-09 16:50:01 +01:00
|
|
|
def parse_input( input )
|
2021-11-09 23:09:07 +01:00
|
|
|
splitted_input = input.split(' ')
|
2021-11-09 16:50:01 +01:00
|
|
|
|
2021-11-10 08:48:34 +01:00
|
|
|
# 2-passes:
|
|
|
|
# 1. regroup strings and programs
|
2021-11-09 21:58:25 +01:00
|
|
|
opened_programs = 0
|
|
|
|
closed_programs = 0
|
|
|
|
string_delimiters = 0
|
2021-11-09 16:50:01 +01:00
|
|
|
regrouping = false
|
2021-11-10 11:01:26 +01:00
|
|
|
|
2021-11-09 23:09:07 +01:00
|
|
|
regrouped_input = []
|
2021-11-09 16:50:01 +01:00
|
|
|
splitted_input.each do |elt|
|
2021-11-09 23:14:42 +01:00
|
|
|
# TODO: handle buried-in-elt « and » (surround by ' ' and re-split)
|
2021-11-09 23:09:07 +01:00
|
|
|
if elt[0] == '«'
|
|
|
|
opened_programs += 1
|
|
|
|
elt.gsub!( '«', '« ') if elt.length > 1 && elt[1] != ' '
|
|
|
|
end
|
|
|
|
string_delimiters += 1 if elt[0] == '"'
|
|
|
|
|
|
|
|
elt = "#{regrouped_input.pop} #{elt}".strip if regrouping
|
|
|
|
|
|
|
|
regrouped_input << elt
|
|
|
|
|
2021-11-10 08:48:34 +01:00
|
|
|
regrouping = string_delimiters.odd? || (opened_programs > closed_programs )
|
2021-11-09 23:09:07 +01:00
|
|
|
|
|
|
|
if elt[-1] == '»'
|
|
|
|
closed_programs += 1
|
|
|
|
elt.gsub!( '»', ' »') if elt.length > 1 && elt[-2] != ' '
|
|
|
|
end
|
|
|
|
string_delimiters += 1 if elt.length > 1 && elt[-1] == '"'
|
|
|
|
end
|
|
|
|
|
|
|
|
# 2. parse
|
|
|
|
parsed_tree = []
|
|
|
|
regrouped_input.each do |elt|
|
2021-11-09 16:50:01 +01:00
|
|
|
parsed_entry = { value: elt }
|
|
|
|
|
2021-11-09 21:58:25 +01:00
|
|
|
opened_programs += 1 if elt[0] == '«'
|
|
|
|
string_delimiters += 1 if elt[0] == '"'
|
|
|
|
|
2021-11-09 23:09:07 +01:00
|
|
|
parsed_entry[:type] = case elt[0]
|
|
|
|
when '«'
|
|
|
|
:program
|
|
|
|
when '"'
|
|
|
|
:string
|
|
|
|
when "'"
|
|
|
|
:name # TODO: check for forbidden space
|
|
|
|
else
|
|
|
|
if numeric?( elt )
|
|
|
|
:numeric
|
2021-11-09 16:50:01 +01:00
|
|
|
else
|
2021-11-09 23:09:07 +01:00
|
|
|
:word
|
2021-11-09 16:50:01 +01:00
|
|
|
end
|
2021-11-09 23:09:07 +01:00
|
|
|
end
|
|
|
|
|
2021-11-09 16:50:01 +01:00
|
|
|
if parsed_entry[:type] == :numeric
|
|
|
|
i = parsed_entry[:value].to_i
|
|
|
|
f = parsed_entry[:value].to_f
|
|
|
|
|
|
|
|
parsed_entry[:value] = i == f ? i : f
|
|
|
|
end
|
|
|
|
|
|
|
|
parsed_tree << parsed_entry
|
|
|
|
end
|
|
|
|
|
|
|
|
parsed_tree
|
|
|
|
end
|
|
|
|
end
|
2021-10-30 23:36:49 +02:00
|
|
|
end
|