华子的代码空间

逆水行舟,不进则退。 关注系统编程、网络编程、并发、分布式。

用LL(1)递归下降语法器构造一个计算器

LL(1)

何为LL(1)?通俗来说就是向前看一个词法单元的自顶向下解析器。两个L都代表left-to-right,第一个L表示解析器按“从左到右”的顺序解析输入内容;第二个L表示下降解析时也是按“从左到右”的顺序遍历子节点。而(1)表示它使用一个向前看 词法单元。

我们从一个简单的计算器来看看递归下降的语法器如何构造。

对于 2 + 3 * 5 的抽象语法树如下:

我们可以使用如下文法表示计算表达式:

# expr ::= expr addop term | term
# term ::= term mulop factor | factor
# factor ::= number | ( expr )
# addop ::= + | -
# mulop ::= * | /

 1 import tokenize, StringIO
 2 
 3 tokens = None
 4 cur_tok = None
 5 
 6 def scan(text):
 7     g = tokenize.generate_tokens(
 8         StringIO.StringIO(text).readline)
 9     return ((v[0], v[1]) for v in g)
10     
11 def get_token():
12     global tokens, cur_tok
13     cur_tok = tokens.next()
14     #print cur_tok
15     return cur_tok
16     
17 def match(type, val = ''):
18     global tokens, cur_tok
19     t, v = cur_tok
20     if t == type or t == tokenize.OP and v == val:
21         get_token()
22     else:
23         raise 
24 
25 def expr():
26     global cur_tok
27     tmp = term()
28     t, v = cur_tok
29     while v == '+' or v == '-':
30         match(tokenize.OP)
31         rhs = term()
32         e = str(tmp) + str(v) + str(rhs)
33         tmp = eval(e)
34         print e, '=', tmp
35         t, v = cur_tok
36     return tmp 
37 
38 def term():
39     global cur_tok
40     tmp = factor()
41     t, v = cur_tok
42     while v == '*' or v == '/':
43         match(tokenize.OP)
44         rhs = factor()
45         e = str(tmp) + str(v) + str(rhs)
46         tmp = eval(e)
47         print e, '=', tmp
48         t, v = cur_tok
49     return tmp
50 
51 def factor():
52     global cur_tok
53     t, v = cur_tok
54     if t == tokenize.NUMBER:
55         match(tokenize.NUMBER)
56         return int(v)
57     elif v == '(':
58         match(tokenize.OP, '(')
59         tmp = expr()
60         match(tokenize.OP, ')')
61         return tmp
62     else:
63         raise
64 
65 if __name__ == '__main__':
66     text = '12 + 2 * ( 5 + 6 )'
67     tokens = scan(text)
68     get_token()
69     res = expr()
70     print text, '=', res

对于12 + 2 * ( 5 + 6 ),运行结果如下:

posted on 2012-12-15 01:41  华子的代码空间  阅读(788)  评论(0编辑  收藏  举报

导航