Skip to content

Instantly share code, notes, and snippets.

@daeken
Created December 28, 2010 05:46
Show Gist options
  • Save daeken/756932 to your computer and use it in GitHub Desktop.
Save daeken/756932 to your computer and use it in GitHub Desktop.
class Identifier(object):
def __init__(self, name):
if isinstance(name, Identifier):
name = name.name
self.name = name
def __repr__(self):
return self.name
class Symbol(Identifier):
def __repr__(self):
return '\'' + self.name
class List(list):
def __repr__(self):
return '(' + ' '.join(map(repr, self)) + ')'
class Parser(object):
def __init__(self, data):
self.data = data
self.off = 0
def getch(self):
return self.data[self.off]
def move(self):
self.off += 1
def parse(self):
ch = self.getch()
while ch in ' \r\n\t':
self.move()
ch = self.getch()
if ch == '(':
return self.parseList()
elif ch == '\'':
return self.parseSymbol()
elif ch in '-0123456789':
return self.parseNumber()
elif ch == '.':
return self.parseDots()
else:
return self.parseIdentifier()
def parseList(self):
self.move()
elems = List()
while self.getch() != ')':
elems.append(self.parse())
self.move()
return elems
def parseIdentifier(self):
identifier = ''
while True:
ch = self.getch()
if ch == '.' or ch == ')' or ch == ' ':
break
identifier += ch
self.move()
return Identifier(identifier)
def parseDots(self):
identifier = ''
while True:
ch = self.getch()
if ch != '.':
break
identifier += ch
self.move()
return Identifier(identifier)
def parseSymbol(self):
self.move()
return Symbol(self.parse())
def parseNumber(self):
number = ''
first = self.getch()
if first in '-+':
number = first
self.move()
seenDot = False
while True:
ch = self.getch()
if ch in '0123456789':
number += ch
elif ch == '.':
assert not seenDot
seenDot = True
number += ch
else:
break
self.move()
if seenDot:
return float(number)
else:
return int(number)
def parse(data):
return Parser(data).parse()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment