Skip to content

Commit

Permalink
complete a crude parse
Browse files Browse the repository at this point in the history
  • Loading branch information
mapan1984 committed Jan 17, 2017
1 parent 91b54b0 commit 7234778
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.vscode
__pycache__
60 changes: 60 additions & 0 deletions py/parse.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from representation import Pair
from split import bulid_exp_list

class Stack:
def __init__(self, line=None):
self.line = line or []
self.index = len(self.line)

def pop(self):
self.index -= 1
return self.line.pop()

def top(self):
return self.line[self.index-1]

def stash(self, val):
self.index += 1
self.line.append(val)

def not_empty(self):
return self.index > 0

def parse(exp_stack):
buffer = Stack()
while exp_stack.not_empty():
val = exp_stack.pop()
if val == ')':
buffer.stash(val)
elif val == '(':
car = buffer.pop()
buffer.pop()
if buffer.not_empty():
if buffer.top() != ')':
cdr = buffer.pop()
val = Pair(car, cdr)
buffer.stash(val)
else:
buffer.stash(car)
else:
return car
else:
if buffer.top() == ')':
buffer.stash(Pair(val, None))
else:
cdr = buffer.pop()
buffer.stash(Pair(val, cdr))

if __name__ == "__main__":
#b1 = Stack(["(", "*", 1, 2, ")"])
#b2 = Stack(["(", "*", "(", "+", 1, 2, ")", 3, ")"])
#val1 = parse(b1)
#val2 = parse(b2)
#print(val1)
#print(val2)
exp = "(lambda (x) (+ 1 x))"
print(exp)
exp = bulid_exp_list(exp)
print(exp)
b3 = Stack(exp)
print(parse(b3))
29 changes: 29 additions & 0 deletions py/representation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
class Pair:
"""Pair: has car and cdr"""

def __init__(self, car, cdr):
self.car = car
self.cdr = cdr

def __repr__(self):
return "<Pair: {car} {cdr}>".format(car=repr(self.car),
cdr=repr(self.cdr))

def __str__(self):
s = "(" + str(self.car)
cdr = self.cdr
while isinstance(cdr, Pair):
s += " " + str(cdr.car)
cdr = cdr.cdr
if cdr is not None:
s += " . " + str(cdr)
return s + ")"

def __len__(self):
n, cdr = 1, self.cdr
while isinstance(cdr, Pair):
n += 1
cdr = cdr.cdr
if cdr is not None:
raise TypeError("length attempted on improper list")
return n
46 changes: 46 additions & 0 deletions py/split.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import string

_NUMERAL_STARTS = set(string.digits) | set('+-.')
_SYMBOL_CHARS = (set('!$%&*/:<=>?@^_~') | set(string.ascii_lowercase) |
set(string.ascii_uppercase) | _NUMERAL_STARTS)
_STRING_DELIMS = set('"')
_WHITESPACE = set(' \t\n\r')
_SINGLE_CHAR_TOKENS = set("()'`")
_TOKEN_END = _WHITESPACE | _SINGLE_CHAR_TOKENS | _STRING_DELIMS | {',', ',@'}
DELIMITERS = _SINGLE_CHAR_TOKENS | {'.', ',', ',@'}

def split_exp_str(line, index=0):
"""返回分割得到的字符串"""
var = []
while index < len(line):
var.clear()
char = line[index]
if char in _WHITESPACE:
index += 1
elif char in _STRING_DELIMS:
index += 1 # 跳过"
char = line[index]
while char not in _STRING_DELIMS:
var.append(char)
index += 1
char = line[index]
index += 1 # 跳过"
yield "".join(var)
elif char in _SINGLE_CHAR_TOKENS:
index += 1
yield char
elif char in _SYMBOL_CHARS:
while char not in _WHITESPACE | _SINGLE_CHAR_TOKENS:
var.append(char)
index += 1
char = line[index]
yield "".join(var)

def bulid_exp_list(line):
exp = []
for var in split_exp_str(line):
exp.append(var)
return exp

if __name__ == "__main__":
print(bulid_exp_list('(define "asd" (+ 1 2) (* 3 4) "adf")'))
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.

0 comments on commit 7234778

Please sign in to comment.