贴上我今天编的实验性代码,这段代码验证了我的思路的可行性
coffeescript语言:
exports.parse = (element, text) ->
global.text = text
global.cursor = 0
global.tokens = []
global.memo = {}
rules[element](0)
match = (c) ->
if text[cursor] is c
cursor++;
true
rules = {
Binary: (start) ->
"Binary: 1 | Binary+1"
hash = 'Binary'+start
m = memo[hash]
if m is undefined
memo[hash] = rules.Unary(start)
rules.Binary(start)
else
if not match('+') then delete memo[hash]; return m
a = rules.Unary(cursor)
if not a then delete memo[hash]; m
else memo[hash] = m+a; rules.Binary(start)
Unary: (start) ->
c = text[cursor]
switch c
when '+'
cursor++;
if text[cursor]=='+' then cursor++; rules.Unary(cursor)+1;
else rules.Unary(cursor)
when '-'
cursor++;
if text[cursor]=='-' then cursor++; rules.Unary(cursor)-1
else -rules.Unary(cursor)
else
x = rules.Atom(start)
if text[cursor]=='+' and text[cursor+1]=='+' then cursor+=2; x+1
else if text[cursor]=='-' and text[cursor+1]=='-' then cursor+=2; x-1
else x
Atom: (start) ->
switch text[cursor]
when '1' then cursor++; 1
when '(' then cursor++; exp = rules.Binary(cursor); match(')'); exp
}
以下是所通过的测试:
"test parse left recursive": (test) ->
test.equal parse('Binary', '1'), 1
test.equal parse('Binary', '++1'), 2
test.equal parse('Binary', '1++'), 2
test.equal parse('Binary', '1--'), 0
test.equal parse('Binary', '(1--)--'), -1
test.equal parse('Binary', '+1'), 1
test.equal parse('Binary', '-1'), -1
test.equal parse('Binary', '--1'), 0
test.equal parse('Binary', '1+1+1'), 3
test.equal parse('Binary', '1+(1+1)'), 3
test.equal parse('Binary', '(1+1)+(1+1)'), 4
test.equal parse('Binary', '1+(1+1+1)+1'), 5
test.done()