{"title": "\u4f7f\u7528Antlr4\u5b9e\u73b0\u8ba1\u7b97\u5668[Python]", "update_time": "2016-07-03 20:04:38", "tags": "antlr4", "pid": "336", "icon": "python.png"}
### 语法和词法 编辑语法文件 `Calculator.g4` 如下 ``` grammar Calculator; expr : expr op=('*'|'/') expr # MULDiv | expr op=('+'|'-') expr # AddSub | INT # int | '(' expr ')' # parens | op=('-'|'+') INT # prehead1 | op=('-'|'+') '(' expr ')' # prehead2 ; INT : [0-9]+; MUL : '*' ; DIV : '/' ; ADD : '+' ; SUB : '-' ; WS : [ \t\r\n]+ -> skip; ``` ### 使用Antlr4 生成解析器框架 ``` antlr4 -visitor -Dlanguage=Python2 Calculator.g4 ``` ### 修改Vistor框架代码,实现计算器的解析和计算 修改 CalculatorVisitor.py文件 ``` # Generated from Calculator.g4 by ANTLR 4.5.3 from antlr4 import * from CalculatorLexer import CalculatorLexer class CalculatorVisitor(ParseTreeVisitor) : # | INT # int def visitInt(self, ctx): return int(ctx.getText()) # | expr op=('+'|'-') expr # AddSub def visitAddSub(self, ctx): left = self.visit(ctx.expr(0)) right = self.visit(ctx.expr(1)) if ctx.op.type == CalculatorLexer.ADD: return left + right else: return left - right # | expr op=('*'|'/') expr # MULDiv def visitMULDiv(self, ctx): left = self.visit(ctx.expr(0)) right = self.visit(ctx.expr(1)) if ctx.op.type == CalculatorLexer.MUL: return left * right else: return left / right # | op=('-'|'+') INT # prehead1 def visitPrehead1(self, ctx): value = int(ctx.INT().getText()) if ctx.op.type == CalculatorLexer.ADD: return value else: return -(value) # | op=('-'|'+') '(' expr ')' # prehead2 def visitPrehead2(self, ctx): value = self.visit(ctx.expr()) if ctx.op.type == CalculatorLexer.ADD: return self.visit(ctx.expr()) else: return -self.visit(ctx.expr()) # | '(' expr ')' # parens def visitParens(self, ctx): return self.visit(ctx.expr()) ``` ### 编写主函数,调用解析器 编写test.py如下: ``` import sys from antlr4 import * from CalculatorParser import CalculatorParser from CalculatorLexer import CalculatorLexer from CalculatorListener import CalculatorListener from CalculatorVisitor import CalculatorVisitor def main(argv): input = FileStream(argv[1]) lexer = CalculatorLexer(input) stream = CommonTokenStream(lexer) parser = CalculatorParser(stream) tree = parser.expr() v = CalculatorVisitor() print v.visit(tree) if __name__ == '__main__': main(sys.argv) ``` * 做个测试 ``` Case 1: cat "7+ 3 * (10 / (12 / (3 + 1) - 1))" > cal.txt python main.py cal.txt 输出结果:22 使用bc计算 cat cal.txt | bc 输出结果: 22 Case 2: cat "-7+ 3 * (10 / (12 / (3 + 1) - 1))" > cal.txt python main.py cal.txt 输出结果:8 使用bc计算 cat cal.txt | bc 输出结果: 8 Case 3: cat "-(7+ 3 * (10 / (12 / (3 + 1) - 1)))" > cal.txt python main.py cal.txt 输出结果:-22 使用bc计算 cat cal.txt | bc 输出结果: -22 ```