From 703595f8f8380acc6816f0a770afee6acba8adc4 Mon Sep 17 00:00:00 2001 From: Nat Lasseter Date: Tue, 30 Jan 2024 16:55:42 +0000 Subject: Initial commit --- lib/sexp/parse.rb | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 lib/sexp/parse.rb (limited to 'lib/sexp/parse.rb') 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 -- cgit v1.2.1