Let's continue learning from the previous part.Graphically,the arithmetic expression can be represented with the following syntax diagram:
A syntax diagram is a graphical represation of a programming language's syntax rules.Basically,a syntax diagram visually show you which statements are allowed in your programming language and which are not.Syntax diagrams sever two main purposes:
1.They graphically responsent the specification(grammar) of a programming language.
2.It can be used to help us write our parser - we can map a diagram to code by following simple rules.
We have known that the process of recognizing a phrase in the stream of tokens is called parsing and the part of an interpreter or a compiler that performs that job is called a parser. Parsing is also called syntax analysis, and the parser is also aptly called a syntax analyzer.
The blog adopted the creatation of a new method to parse an integer and named it term:
def term(self):
"""Return an INTEGER token value"""
token = self.current_token
self.eat(INTEGER)
return token.value
def expr(self):
"""Parser / Interpreter """
# set current token to the first token taken from the input
self.current_token = self.get_next_token()
result = self.term()
while self.current_token.type in (PLUS, MINUS):
token = self.current_token
if token.type == PLUS:
self.eat(PLUS)
result = result + self.term()
elif token.type == MINUS:
self.eat(MINUS)
result = result - self.term()
return result
The following code is modified on the basis of original blog code.It allows inputting multiple numbers and performing addition,subtraction,multiplication and division operation:
1 INTEGER , PLUS , MINUS , MULTI , DIV , EOF = 'INTEGER','PLUS','MINUS','MULTI','DIV','EOF' 2 3 class Token(object): 4 def __init__(self,type,value): 5 self.type = type 6 self.value = value 7 8 def __str__(self): 9 return 'Token({type},{value})'.format( 10 type = self.type, 11 value = self.value 12 ) 13 14 def __repr__(self): 15 return self.__str__() 16 17 class Interpreter(object): 18 def __init__(self,text): 19 self.text = text 20 self.pos = 0 21 self.current_token = None 22 self.current_char = self.text[self.pos] 23 24 def error(self): 25 raise Exception('Invalid syntax') 26 27 def advance(self): 28 self.pos += 1 29 if self.pos > len(self.text) - 1: 30 self.current_char = None 31 else: 32 self.current_char = self.text[self.pos] 33 34 def skip_whitespace(self): 35 while self.current_char is not None and self.current_char.isspace(): 36 self.advance() 37 38 def integer(self): 39 result = '' 40 while self.current_char is not None and self.current_char.isdigit(): 41 result += self.current_char 42 self.advance() 43 return int(result) 44 45 def get_next_token(self): 46 while self.current_char is not None: 47 if self.current_char.isspace(): 48 self.skip_whitespace() 49 continue 50 elif self.current_char.isdigit(): 51 return Token(INTEGER,self.integer()) 52 elif self.current_char == '+': 53 self.advance() 54 return Token(PLUS,'+') 55 elif self.current_char == '-': 56 self.advance() 57 return Token(MINUS,'-') 58 elif self.current_char == '*': 59 self.advance() 60 return Token(MULTI,'*') 61 elif self.current_char == '/': 62 self.advance() 63 return Token(DIV,'/') 64 self.error() 65 return Token(EOF,'EOF') 66 67 def eat(self,token_type): 68 if self.current_token.type == token_type: 69 self.current_token = self.get_next_token() 70 else: 71 self.error() 72 73 def term(self): 74 """ 75 :return: an INTEGER value 76 """ 77 token = self.current_token 78 self.eat(INTEGER) 79 return token.value 80 81 def expr(self): 82 self.current_token = self.get_next_token() 83 result = self.term() 84 while self.current_token.type in(PLUS,MINUS,MULTI,DIV): 85 token = self.current_token 86 if token.type == PLUS: 87 self.eat(PLUS) 88 result += self.term() 89 elif token.type == MINUS: 90 self.eat(MINUS) 91 result -= self.term() 92 elif token.type == MULTI: 93 self.eat(MULTI) 94 result *= self.term() 95 elif token.type == DIV: 96 self.eat(DIV) 97 result /= self.term() 98 else: 99 self.error() 100 return result 101 102 def main(): 103 while True: 104 try: 105 text = input('calc>') 106 except EOFError: 107 break 108 if not text: 109 continue 110 interpreter = Interpreter(text) 111 result = interpreter.expr() 112 print(result) 113 114 if __name__ == '__main__': 115 main()