Sha256: e8b96f78e74170fceb528337b54b3ad95399b4b98f8c73c7b666ccbe1a615505
Contents?: true
Size: 1.36 KB
Versions: 1
Compression:
Stored size: 1.36 KB
Contents
# frozen_string_literal: true require 'strscan' class Sexpistol class Parser < StringScanner PARANTHESES = /[()]/.freeze STRING = /"([^"\\]|\\.)*"/.freeze FLOAT = /[\-+]? [0-9]+ ((e[0-9]+) | (\.[0-9]+(e[0-9]+)?)) (?=[\s()])/x.freeze INTEGER = /([\-+]?[0-9]+)(?=[\s()])/.freeze SYMBOL = /[^0-9()\s]+[^()\s]*/.freeze def initialize(string) raise 'String given is not an s-expression' if string.strip[0] != '(' raise 'Invalid s-expression' if string.count('(') != string.count(')') super(string.strip) end def parse(level = 0, exp = []) until eos? case token = fetch_token when ')' then break when '(' then exp << parse(level + 1) when String, Integer, Float, Symbol then exp << token end end if level.zero? exp = exp.first if exp.first.is_a?(Array) && exp.length == 1 exp = Sexpistol::SExpressionArray.new(exp) if exp.all? { |item| item.is_a?(Array) } end exp end def fetch_token skip(/\s+/) return matched if scan(PARANTHESES) return matched.undump if scan(STRING) return matched.to_f if scan(FLOAT) return matched.to_i if scan(INTEGER) return matched.to_sym if scan(SYMBOL) raise "Invalid token at position #{pos} near '#{scan(/.{0,20}/)}'." end end end
Version data entries
1 entries across 1 versions & 1 rubygems
Version | Path |
---|---|
sexpistol-0.1.1 | lib/sexpistol/parser.rb |