rpl.rb/lib/parser.rb

82 lines
2.1 KiB
Ruby
Raw Normal View History

2021-10-30 23:36:49 +02:00
# coding: utf-8
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