rpl.rb/lib/parser.rb

91 lines
2.5 KiB
Ruby
Raw Normal View History

2021-12-07 16:09:17 +01:00
# frozen_string_literal: true
2021-10-30 23:36:49 +02:00
module Rpl
2021-12-07 15:50:58 +01:00
module Lang
class Parser
def initialize; end
def numeric?( elt )
!Float(elt).nil?
2021-11-23 16:54:23 +01:00
rescue ArgumentError
2021-12-07 15:50:58 +01:00
begin
!Integer(elt).nil?
rescue ArgumentError
false
end
2021-11-23 16:54:23 +01:00
end
2021-10-30 23:36:49 +02:00
2021-12-07 15:50:58 +01:00
def parse_input( input )
splitted_input = input.split(' ')
# 2-passes:
# 1. regroup strings and programs
opened_programs = 0
closed_programs = 0
string_delimiters = 0
regrouping = false
regrouped_input = []
splitted_input.each do |elt|
# TODO: handle buried-in-elt « and » (surround by ' ' and re-split)
if elt[0] == '«'
opened_programs += 1
elt.gsub!( '«', '« ') if elt.length > 1 && elt[1] != ' '
end
string_delimiters += 1 if elt[0] == '"'
2021-11-09 23:09:07 +01:00
2021-12-07 15:50:58 +01:00
elt = "#{regrouped_input.pop} #{elt}".strip if regrouping
2021-11-09 23:09:07 +01:00
2021-12-07 15:50:58 +01:00
regrouped_input << elt
2021-11-09 23:09:07 +01:00
2021-12-07 15:50:58 +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] == '"'
2021-11-24 15:04:27 +01:00
2021-12-07 15:50:58 +01:00
regrouping = string_delimiters.odd? || (opened_programs > closed_programs )
end
2021-11-09 23:09:07 +01:00
2021-12-07 15:50:58 +01:00
# 2. parse
parsed_tree = []
regrouped_input.each do |elt|
parsed_entry = { value: elt }
opened_programs += 1 if elt[0] == '«'
string_delimiters += 1 if elt[0] == '"'
parsed_entry[:type] = case elt[0]
when '«'
:program
when '"'
:string
when "'"
:name # TODO: check for forbidden space
2021-11-09 16:50:01 +01:00
else
2021-12-07 15:50:58 +01:00
if numeric?( elt )
:numeric
else
:word
end
2021-11-09 16:50:01 +01:00
end
2021-11-09 23:09:07 +01:00
2021-12-07 15:50:58 +01:00
if parsed_entry[:type] == :numeric
parsed_entry[:base] = 10 # TODO: parse others possible bases 0x...
2021-12-07 15:50:58 +01:00
begin
parsed_entry[:value] = Float( parsed_entry[:value] )
rescue ArgumentError
parsed_entry[:value] = Integer( parsed_entry[:value] )
end
2021-11-23 16:54:23 +01:00
end
2021-12-07 15:50:58 +01:00
parsed_tree << parsed_entry
2021-11-09 16:50:01 +01:00
end
2021-12-07 15:50:58 +01:00
parsed_tree
2021-11-09 16:50:01 +01:00
end
end
end
2021-10-30 23:36:49 +02:00
end