想了解编译器原理的朋友, 不要在看龙书或者其他的书了, 强烈推荐先看《编程语言实现模式》. 英文名叫 Language Implementation Patterns - Create Your Own Domain-Specific and General Programming Languages. 它实战性非常强, 在也不会被催眠了.
来实现一个简单的词法解析器, 解析简单的数字运算, 只支持整数和加减. 原理我不多说, 想了解的就去看我推荐 《编程语言实现模式》.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 class Token : def __init__ (self, typ, value) : self.typ = typ self.value = value def __str__ (self) : return '<type="%s", value="%s">' % (self.typ, self.value) class Lexer : def __init__ (self, text) : ''' text:输入字符 p:当前输入字符的下标 c:当前字符 eof:结束标志 ''' self.text = text self.text_len = len(text) self.p = 0 self.c = self.text[self.p] self.eof = 'eof' def consume (self) : '''向前移动一个字符, 检测输入是否结束''' self.p += 1 if self.p >= self.text_len: self.c = self.eof else : self.c = self.text[self.p] def match (self, x) : '''确保x是输入流中的下一个字符''' if self.c == x: self.consume() else : raise ValueError('expecting %s ; found %s' % (x, self.c)) def next_token (self) : raise NotImplementedError() class ListLexer (Lexer) : def __init__ (self, text) : super().__init__(text) def next_token (self) : while self.c != self.eof: if (self.c == ' ' or self.c == '\t' or self.c == '\n' or self.c == '\r' ): self.r_ws() continue elif self.c == '+' : self.consume() return Token('OP' , '+' ) elif self.c == '-' : self.consume() return Token('OP' , '-' ) else : if self.is_number(): return self.r_number() raise ValueError('invalid character: %s' % (self.c)) return Token('EOF' , 'eof' ) def r_number (self) : buf = [] while self.is_number(): buf.append(self.c) self.consume() return Token('NUMBER' , '' .join(buf)) def r_ws (self) : while (self.c == ' ' or self.c == '\t' or self.c == '\n' or self.c == '\r' ): self.consume() def is_number (self) : return '0' <= self.c <= '9' if __name__ == '__main__' : text = '''01+ 22''' lexer = ListLexer(text) t = lexer.next_token() while t.typ != 'EOF' : print(t) t = lexer.next_token() print(t)