Skip to content

Instantly share code, notes, and snippets.

@threedaymonk
Last active January 3, 2016 22:29
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save threedaymonk/8528281 to your computer and use it in GitHub Desktop.
Save threedaymonk/8528281 to your computer and use it in GitHub Desktop.
Little Schemer group, chapter 1
(car (cons 1 (list 2 3)))
(list 4 5)
.PHONY: clean all
all: diag.pdf
diag.dot: example.scm
ruby ./vis.rb < example.scm > diag.dot
diag.pdf: diag.dot
dot -Tpdf < diag.dot > diag.pdf
clean:
rm -f diag.dot diag.pdf
require "./parser"
p Parser.parse_program($stdin.read)
require 'strscan'
module Parser
module_function
def parse_expression(scanner)
if scanner.scan(/\(/)
parse_list(scanner)
elsif scanner.scan(/\s/)
return :space
elsif scanner.scan(/\)/)
return :rparen
elsif str = scanner.scan(/[^\s\(\)]+/)
return parse_atom(str)
elsif scanner.eos?
return :eos
else
raise "dunno before #{scanner.rest}"
end
end
def parse_atom(str)
return str
end
def parse_list(scanner)
list = []
loop do
element = parse_expression(scanner)
case element
when :rparen
return list
when :space
# ignore me
when :eos
raise "unexpected end of input"
else
list << element
end
end
raise "unbalanced parentheses before #{scanner.rest}"
end
def parse_program(string)
scanner = StringScanner.new(string)
list = []
loop do
element = parse_expression(scanner)
case element
when :eos
return list
when :space
# ignore me
else
list << element
end
end
end
end
require "./parser.rb"
def label_node(node)
if node.respond_to?(:each)
%(a#{node.object_id} [label="List" shape="rect"])
else
%(a#{node.object_id} [label="#{node.inspect.gsub(/"/, "'")}"];)
end
end
def render_edges(structure, acc = [])
structure.each do |e|
acc << label_node(structure)
acc << label_node(e)
acc << "a#{structure.object_id} -> a#{e.object_id};"
if e.respond_to?(:each)
render_edges(e, acc)
end
end
acc
end
structure = Parser.parse_program($stdin.read)
puts "digraph G {"
puts render_edges(structure).join("\n")
puts "}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment