Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Fetching contributors…

Cannot retrieve contributors at this time

95 lines (72 sloc) 2.181 kB
# Reproduces [1] using parslet.
# [1] http://thingsaaronmade.com/blog/a-quick-intro-to-writing-a-parser-using-treetop.html
$:.unshift File.dirname(__FILE__) + "/../lib"
require 'pp'
require 'parslet'
require 'parslet/convenience'
module MiniLisp
class Parser < Parslet::Parser
root :expression
rule(:expression) {
space? >> str('(') >> space? >> body >> str(')') >> space?
}
rule(:body) {
(expression | identifier | float | integer | string).repeat.as(:exp)
}
rule(:space) {
match('\s').repeat(1)
}
rule(:space?) {
space.maybe
}
rule(:identifier) {
(match('[a-zA-Z=*]') >> match('[a-zA-Z=*_]').repeat).as(:identifier) >> space?
}
rule(:float) {
(
integer >> (
str('.') >> match('[0-9]').repeat(1) |
str('e') >> match('[0-9]').repeat(1)
).as(:e)
).as(:float) >> space?
}
rule(:integer) {
((str('+') | str('-')).maybe >> match("[0-9]").repeat(1)).as(:integer) >> space?
}
rule(:string) {
str('"') >> (
str('\\') >> any |
str('"').absent? >> any
).repeat.as(:string) >> str('"') >> space?
}
end
class Transform
include Parslet
attr_reader :t
def initialize
@t = Parslet::Transform.new
# To understand these, take a look at what comes out of the parser.
t.rule(:identifier => simple(:ident)) { ident.to_sym }
t.rule(:string => simple(:str)) { str }
t.rule(:integer => simple(:int)) { Integer(int) }
t.rule(:float=>{:integer=> simple(:a), :e=> simple(:b)}) { Float(a + b) }
t.rule(:exp => subtree(:exp)) { exp }
end
def do(tree)
t.apply(tree)
end
end
end
parser = MiniLisp::Parser.new
transform = MiniLisp::Transform.new
result = parser.parse_with_debug %Q{
(define test (lambda ()
(begin
(display "something")
(display 1)
(display 3.08))))
}
# Transform the result
pp transform.do(result) if result
# Thereby reducing it to the earlier problem:
# http://github.com/kschiess/toylisp
Jump to Line
Something went wrong with that request. Please try again.