zoukankan      html  css  js  c++  java
  • 用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 ),运行结果如下:

  • 相关阅读:
    经典小程序源码及其下载地址
    基于cropper.js的图片上传和裁剪
    【组件】微信小程序input搜索框的实现
    如何打造个人技术影响力
    一位90后程序员的自述:如何从年薪3w到30w!
    状态模式(State)(开关灯,状态实例为类,不同状态,不同行为)
    责任链模式(Chain of Responsibility、Handler)(请求处理建立链)
    java中创建对象的五种方法
    PrintWrite
    观察者模式(Observer、Subject、ConcreteSubject、ConcreteObserver)(监护、订阅)
  • 原文地址:https://www.cnblogs.com/huazi/p/2818881.html
Copyright © 2011-2022 走看看