Fer*_*mac 5 python assembly antlr
我正在尝试使用ANTLR来获取简单的语法并生成汇编输出.我在ANTLR中选择的语言是Python.
许多教程似乎非常复杂或精心处理与我无关的事情; 我只需要一些非常简单的功能.所以我有两个问题:
将值从一个规则"返回"到另一个规则.
所以,假设我有一条规则:
赋值:name = IDENTIFIER ASSIGNMENT表达式;
当识别此规则时,我可以在{}中运行Python代码,并且我可以通过执行以下操作将args传递给Python代码以进行表达:
赋值:name = IDENTIFIER ASSIGNMENT表达式[variablesList];
然后
表达式[variablesList]:等等等等
但是,我如何"返回"原始规则的值?例如,我如何计算表达式的值,然后将其发送回我的分配规则以在Python中使用?
如何写出目标语言代码?
所以我有一些Python在规则被识别时运行,然后我计算我希望该语句产生的程序集.但是我如何说"将这个汇编指令字符串写入我的目标文件"?
任何与这种东西相关的好教程(属性语法,编译成AST以外的东西等)也会有所帮助.如果我的问题没有太大意义,请让我澄清一下; 我很难缠绕在ANTLR周围.
Bar*_*ers 10
假设您要解析简单表达式并在运行时提供可在这些表达式中使用的变量映射.一个简单的语法,包括自定义Python代码,returns规则中的语句,以及vars语法入口点的参数,如下所示:
grammar T;
options {
language=Python;
}
@members {
variables = {}
}
parse_with [vars] returns [value]
@init{self.variables = vars}
: expression EOF {value = $expression.value}
;
expression returns [value]
: addition {value = $addition.value}
;
addition returns [value]
: e1=multiplication {value = $e1.value}
( '+' e2=multiplication {value = value + $e2.value}
| '-' e2=multiplication {value = value - $e2.value}
)*
;
multiplication returns [value]
: e1=unary {value = $e1.value}
( '*' e2=unary {value = value * $e2.value}
| '/' e2=unary {value = value / $e2.value}
)*
;
unary returns [value]
: '-' atom {value = -1 * $atom.value}
| atom {value = $atom.value}
;
atom returns [value]
: Number {value = float($Number.text)}
| ID {value = self.variables[$ID.text]}
| '(' expression ')' {value = $expression.value}
;
Number : '0'..'9'+ ('.' '0'..'9'+)?;
ID : ('a'..'z' | 'A'..'Z')+;
Space : ' ' {$channel=HIDDEN};
Run Code Online (Sandbox Code Playgroud)
如果您现在使用ANTLR v3.1.3(没有更高版本!)生成解析器:
java -cp antlr-3.1.3.jar org.antlr.Tool T.g
并运行脚本:
#!/usr/bin/env python
import antlr3
from antlr3 import *
from TLexer import *
from TParser import *
input = 'a + (1.0 + 2) * 3'
lexer = TLexer(antlr3.ANTLRStringStream(input))
parser = TParser(antlr3.CommonTokenStream(lexer))
print '{0} = {1}'.format(input, parser.parse_with({'a':42}))
Run Code Online (Sandbox Code Playgroud)
您将看到正在打印的以下输出:
a + (1.0 + 2) * 3 = 51.0
请注意,您可以定义多个"返回"类型:
parse
: foo {print 'a={0} b={1} c={2}'.format($foo.a, $foo.b, $foo.c)}
;
foo returns [a, b, c]
: A B C {a=$A.text; b=$B.text; b=$C.text}
;
Run Code Online (Sandbox Code Playgroud)
最简单的方法是简单地将print语句放在自定义代码块中并将输出传递给文件:
parse_with [vars]
@init{self.variables = vars}
: expression EOF {print 'OUT:', $expression.value}
;
Run Code Online (Sandbox Code Playgroud)
然后像这样运行脚本:
./run.py > out.txt
Run Code Online (Sandbox Code Playgroud)
这将创建一个文件'out.txt',其中包含:OUT: 51.0.如果你的语法不是那么大,你可能会侥幸逃脱.但是,这可能会有点混乱,在这种情况下,您可以将解析器的输出设置为template:
options {
output=template;
language=Python;
}
Run Code Online (Sandbox Code Playgroud)
并通过您自己定义的模板发出自定义代码.
看到: