summaryrefslogtreecommitdiff
path: root/lib/sexp/parse.rb
diff options
context:
space:
mode:
authorNat Lasseter <user@4574.co.uk>2024-01-30 16:55:42 +0000
committerNat Lasseter <user@4574.co.uk>2024-01-30 16:55:42 +0000
commit703595f8f8380acc6816f0a770afee6acba8adc4 (patch)
treea82e38fb62a867964e23a7edde152a65cfcd7f29 /lib/sexp/parse.rb
Initial commit
Diffstat (limited to 'lib/sexp/parse.rb')
-rw-r--r--lib/sexp/parse.rb118
1 files changed, 118 insertions, 0 deletions
diff --git a/lib/sexp/parse.rb b/lib/sexp/parse.rb
new file mode 100644
index 0000000..adfd513
--- /dev/null
+++ b/lib/sexp/parse.rb
@@ -0,0 +1,118 @@
+class Atom
+ def initialize(content = nil)
+ @content = content
+ end
+
+ attr_reader :content
+
+ def to_s
+ content
+ end
+
+ def self.from_token(token)
+ new(token.content)
+ end
+end
+
+class SExp
+ def initialize(addr = nil, data = nil)
+ @addr = addr
+ @data = data
+ end
+
+ def car
+ @addr
+ end
+ def car=(addr)
+ @addr = addr
+ end
+
+ def cdr
+ @data
+ end
+ def cdr=(data)
+ @data = data
+ end
+
+ def to_s
+ if car.nil?
+ "()"
+ elsif cdr.nil?
+ "(#{car} . ())"
+ else
+ "(#{car} . #{cdr})"
+ end
+ end
+end
+
+def peek_token(tokens)
+ tokens.first
+end
+
+def get_token(tokens)
+ tokens.shift
+end
+
+def num_members(tokens)
+ members = 0
+ level = 1
+ at = 1
+
+ until level == 0
+ case tokens.at(at)
+ when T_LParen
+ members += 1 if level == 1
+ level += 1
+ when T_RParen
+ level -= 1
+ when T_Atom
+ members += 1 if level == 1
+ end
+ at += 1
+ end
+
+ members
+end
+
+def members_to_tree(members)
+ case members.length
+ when 0
+ nil
+ when 1
+ SExp.new(members[0], SExp.new)
+ when 2
+ SExp.new(members[0], members[1])
+ else
+ SExp.new(members[0], members_to_tree(members[1..-1]))
+ end
+end
+
+def parse_sexp(tokens)
+ need = num_members(tokens)
+ get_token(tokens)
+
+ members = []
+
+ need.times do
+ case peek_token(tokens)
+ when T_Atom
+ members << Atom.from_token(get_token(tokens))
+ when T_LParen
+ members << parse_sexp(tokens)
+ end
+ end
+
+ get_token(tokens)
+
+ members_to_tree(members)
+end
+
+def parse_sexps(tokens)
+ sexps = []
+
+ until tokens.empty?
+ sexps << parse_sexp(tokens)
+ end
+
+ sexps
+end