2021-10-18 17:15:28 +00:00
|
|
|
# Based on fast-sexpr (https://www.npmjs.com/package/fast-sexpr)
|
|
|
|
|
|
|
|
module Sexpr
|
|
|
|
extend self
|
|
|
|
|
|
|
|
VERSION = {{ `shards version`.stringify.chomp }}
|
|
|
|
|
2021-10-20 19:00:55 +00:00
|
|
|
alias Node = String | Body
|
|
|
|
alias Body = Array(String) | Array(Node)
|
2021-10-18 17:15:28 +00:00
|
|
|
|
2021-12-27 17:57:19 +00:00
|
|
|
class Parser
|
2021-10-18 17:15:28 +00:00
|
|
|
private property i = 0
|
|
|
|
private property source : String
|
|
|
|
|
2021-12-27 17:57:19 +00:00
|
|
|
module Terms
|
2021-10-18 17:15:28 +00:00
|
|
|
STRING = /"/
|
|
|
|
SPACE = /\s/
|
|
|
|
LIST = /(#{SPACE})|[()]/
|
|
|
|
end
|
|
|
|
|
|
|
|
def initialize(@source : String)
|
|
|
|
end
|
|
|
|
|
|
|
|
private def get_char : Char?
|
|
|
|
if @i == @source.size
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
|
|
|
|
char = @source[@i]
|
|
|
|
@i += 1
|
|
|
|
char
|
|
|
|
end
|
|
|
|
|
|
|
|
private def read_value(is_terminator : Regex) : String
|
|
|
|
value = ""
|
2021-12-27 18:40:09 +00:00
|
|
|
while !is_terminator.matches?(str_char = get_char.to_s)
|
|
|
|
value += str_char
|
2021-10-18 17:15:28 +00:00
|
|
|
end
|
|
|
|
|
|
|
|
value
|
|
|
|
end
|
|
|
|
|
2021-12-27 18:40:09 +00:00
|
|
|
private def un_get_char : Nil
|
2021-10-18 17:15:28 +00:00
|
|
|
@i -= 1
|
|
|
|
end
|
|
|
|
|
2021-10-20 19:00:55 +00:00
|
|
|
def parse : Body
|
|
|
|
body = [] of Node
|
2021-10-18 17:15:28 +00:00
|
|
|
|
|
|
|
while char = get_char
|
|
|
|
if char == ')'
|
|
|
|
break
|
|
|
|
elsif char == '('
|
|
|
|
body << parse
|
|
|
|
elsif char == '"'
|
2021-10-20 19:00:55 +00:00
|
|
|
body << read_value(Terms::STRING)
|
2021-10-18 17:15:28 +00:00
|
|
|
elsif !Terms::SPACE.matches?(char.to_s)
|
|
|
|
un_get_char
|
2021-10-20 19:00:55 +00:00
|
|
|
body << read_value(Terms::LIST)
|
2021-10-18 17:15:28 +00:00
|
|
|
un_get_char
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
body
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-10-19 15:26:49 +00:00
|
|
|
def remove_comments(source : String) : String
|
|
|
|
source.gsub(/;;?.+/, nil)
|
|
|
|
end
|
|
|
|
|
2021-10-20 19:00:55 +00:00
|
|
|
def parse(source : String) : Body
|
2021-12-27 17:57:19 +00:00
|
|
|
Parser.new(remove_comments(source)).parse
|
2021-10-18 17:15:28 +00:00
|
|
|
end
|
|
|
|
end
|