第2章 實現一份LR(0)演算法

趙年峰發表於2013-05-24

首先 我們寫一個前一節的例子3的文法的編譯器的翻譯器。

為了方便不懂python的讀者也能看懂程式碼的意思。我會增加大量的文字來介紹。

2.1 文法物件的定義

下面就是我們的文法物件:

grammar = {
    'S' : [
        RuleObject( ['S' , 'start'] )
    ],
    'start' : [ 
        RuleObject( ['start' ,'expression'] ) 
    ],
    'expression' : [
        RuleObject( ['expression','multExpression'] ),
        RuleObject( ['expression','expression','PLUS','multExpression'] ),
        RuleObject( ['expression','expression','DASH','multExpression'] )
    ],
    'multExpression' : [
        RuleObject( ['multExpression','subExpression' ] ),
        RuleObject( ['multExpression','multExpression', 'MULT', 'subExpression'] ),
        RuleObject( ['multExpression','multExpression', 'SLASH', 'subExpression'] )
    ],
    'subExpression' : [
        RuleObject( ['subExpression','LPAREN', 'expression', 'RPAREN'] ) ,
        RuleObject( ['subExpression','primary' ] )
    ],
    'primary' : [ RuleObject(['primary','NON_INTEGER_3']) ]
}

2.2 終結符和非終結符

下面是文法grammar中出現的非終結符:

nonTerminals = ['start','expression','multExpression','subExpression','primary']

下面是文法grammar中出現的終結符:

terminals = ['PLUS','DASH','MULT','SLASH','LPAREN','RPAREN','NON_INTEGER_3']

2.3規則物件的實體

下面是一個規則物件的實體:

class RuleObject(object):
    def __init__(self,Item):
        self.position = 0
        self.expressionName = Item[0]
        self.item = Item[1:]
        self.pr = list(self.item)
        self.pr.insert(self.position,".")

    def lrNext(self):
        if self.position+1 > len(self.item) :
            return False
        else:
            self.position += 1
        self.pr = list(self.item)
        self.pr.insert(self.position,".")
        return True

    def __str__(self):
        if self.item:
            return "%s -> %s" % (self.expressionName," ".join(self.pr))
        else:
            return "%s -> <empty>" % self.expressionName

    def __repr__(self):
        return "LRItem(%s)" % ( str(self) )

    def lrCurrent(self):
        if self.position >= len(self.item) : return None
        return self.item[self.position]
    def __eq__(self, other):
        if other.__class__ is RuleObject :
            if other.expressionName == self.expressionName:
                if other.item == self.item:
                    return True
            return False
        else:
            return False

首先我們先說明這個類裡面重新定義了物件轉換成str和

下面是一個規則列表物件

class RuleList(list):
    def __contains__(self, item):
        for x in self:
            if item == x :
                return True
        return False

2.4 LR的演算法的重要概念

以下3個概念是實現LR(0)演算法的重要部分。

goto 主要負責移動,並分解具體的非終結符。

def lr0GOTO(I,X):

    J = RuleList()
    for i in I:
        if i.lrCurrent() == X:
            i.lrNext()
            J.append(copy.deepcopy(i) )
    return lr0Closure(J)

item 執行主要的分析工作。

def lr0Item(G):
    C = collections.deque( [ lr0Closure(G['S']) ] );

    p = copy.deepcopy(C)
    while True:
        x = C.pop()
        sysum = {}
        for i in x:
            if i.lrCurrent() != None:
                sysum[i.lrCurrent()] = None
        if x not in p : p.append(x)
        if sysum == {} :
            continue
        for s in sysum :
            sub = lr0GOTO(copy.deepcopy(x),s)
            if sub not in p : C.append(copy.deepcopy(sub))        
        if len(C) == 0 : break

closure 分析一個文法項,並提取其中的子項形成整體的包含項。

def lr0Closure(I):
    O = collections.deque(I)
    p = []
    while True:
        x = O.pop()
        if x.lrCurrent() in nonTerminals and x.lrCurrent() != x.expressionName :
            for y in grammar[x.lrCurrent()]:
                O.appendleft(copy.deepcopy(y))
        p.append(x)
        if len(O) == 0 : break
    return p

2.1 文法物件的定義

下面就是我們的文法物件:

grammar = {
    'S' : [
        RuleObject( ['S' , 'start'] )
    ],
    'start' : [ 
        RuleObject( ['start' ,'expression'] ) 
    ],
    'expression' : [
        RuleObject( ['expression','multExpression'] ),
        RuleObject( ['expression','expression','PLUS','multExpression'] ),
        RuleObject( ['expression','expression','DASH','multExpression'] )
    ],
    'multExpression' : [
        RuleObject( ['multExpression','subExpression' ] ),
        RuleObject( ['multExpression','multExpression', 'MULT', 'subExpression'] ),
        RuleObject( ['multExpression','multExpression', 'SLASH', 'subExpression'] )
    ],
    'subExpression' : [
        RuleObject( ['subExpression','LPAREN', 'expression', 'RPAREN'] ) ,
        RuleObject( ['subExpression','primary' ] )
    ],
    'primary' : [ RuleObject(['primary','NON_INTEGER_3']) ]
}

對於不瞭解python的讀者,我做以下解釋:{}為python的字典型別 比如 { 'S' : [] } 中的'S是字典的名字 ,[]是字典的內容,內容為一個陣列。

這一章節主要定義了一個文法的結構。如果是標準的文法表述,應該如下:

為了方便我在以下每條rule上增加一個;
做為一條規則的結束標準
---------------------------------
    S : S start

    start : expression
    ;

    expression : multExpression
    | expression PLUS multExpression
    | expression DASH multExpression
    ;

    multExpression : subExpression
    | multExpression MULT subExpression
    | multExpression SLASH subExpression
    ;

    subExpression :  LPAREN expression RPAREN
    | primary
    ;

    primary : NON_INTEGER_3
    ;
---------------------------------

上面的規則解釋就是有優先順序別的計算器解析程式,如果稍微增加一些程式碼就可以實現基本的帶有括號和優先順序的加減乘除功能。下一節將詳細講解上面的結構。

2.2 終結符和非終結符

下面是文法grammar中出現的非終結符:

nonTerminals = ['start','expression','multExpression','subExpression','primary']

下面是文法grammar中出現的終結符:

terminals = ['PLUS','DASH','MULT','SLASH','LPAREN','RPAREN','NON_INTEGER_3']

2.3規則物件的實體

下面是一個規則物件的實體:

class RuleObject(object):
    def __init__(self,Item):
        self.position = 0
        self.expressionName = Item[0]
        self.item = Item[1:]
        self.pr = list(self.item)
        self.pr.insert(self.position,".")

    def lrNext(self):
        if self.position+1 > len(self.item) :
            return False
        else:
            self.position += 1
        self.pr = list(self.item)
        self.pr.insert(self.position,".")
        return True

    def __str__(self):
        if self.item:
            return "%s -> %s" % (self.expressionName," ".join(self.pr))
        else:
            return "%s -> <empty>" % self.expressionName

    def __repr__(self):
        return "LRItem(%s)" % ( str(self) )

    def lrCurrent(self):
        if self.position >= len(self.item) : return None
        return self.item[self.position]
    def __eq__(self, other):
        if other.__class__ is RuleObject :
            if other.expressionName == self.expressionName:
                if other.item == self.item:
                    return True
            return False
        else:
            return False

首先我們先說明這個類裡面重新定義了物件轉換成str和

下面是一個規則列表物件

class RuleList(list):
    def __contains__(self, item):
        for x in self:
            if item == x :
                return True
        return False

2.4 LR的演算法的重要概念

以下3個概念是實現LR(0)演算法的重要部分。

goto 主要負責移動,並分解具體的非終結符。

def lr0GOTO(I,X):

    J = RuleList()
    for i in I:
        if i.lrCurrent() == X:
            i.lrNext()
            J.append(copy.deepcopy(i) )
    return lr0Closure(J)

item 執行主要的分析工作。

def lr0Item(G):
    C = collections.deque( [ lr0Closure(G['S']) ] );

    p = copy.deepcopy(C)
    while True:
        x = C.pop()
        sysum = {}
        for i in x:
            if i.lrCurrent() != None:
                sysum[i.lrCurrent()] = None
        if x not in p : p.append(x)
        if sysum == {} :
            continue
        for s in sysum :
            sub = lr0GOTO(copy.deepcopy(x),s)
            if sub not in p : C.append(copy.deepcopy(sub))        
        if len(C) == 0 : break

closure 分析一個文法項,並提取其中的子項形成整體的包含項。

def lr0Closure(I):
    O = collections.deque(I)
    p = []
    while True:
        x = O.pop()
        if x.lrCurrent() in nonTerminals and x.lrCurrent() != x.expressionName :
            for y in grammar[x.lrCurrent()]:
                O.appendleft(copy.deepcopy(y))
        p.append(x)
        if len(O) == 0 : break
    return p

2.5 不定點原理及其講解

2.5 不定點原理及其講解

2.6 主流的LR解釋生成器的演算法

2.6 主流的LR解釋生成器的演算法

相關文章