两个基本的ANTLR问题 [英] Two basic ANTLR questions

查看:124
本文介绍了两个基本的ANTLR问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想用ANTLR采取简单的语法和生产装配输出。我在ANTLR选择的语言是Python。

I'm trying to use ANTLR to take a simple grammar and produce assembly output. My language of choice in ANTLR is Python.

很多教程看起来很复杂或阐述的东西都与我无关;我只是真的需要一些非常简单的功能。所以,我有两个问题:

Many tutorials seem very complicated or elaborate on things that aren't relevant to me; I only really need some very simple functionality. So I have two questions:

'返回'从一个规则值到另一个。

所以我们可以说我有这样的规则:

So let's say I have a rule like:

赋值:名称=标识符分配前pression;

assignment: name=IDENTIFIER ASSIGNMENT expression;

我可以运行在Python中{code}当这个规​​则是公认的s和我可以做这样的事情通过args设置为Python的code为前pression:

I can run Python code in {}s when this rule is recognised, and I can pass args to the Python code for expression by doing something like:

赋值:名称=标识符分配前pression [variablesList];

assignment: name=IDENTIFIER ASSIGNMENT expression[variablesList];

然后

EX pression [variablesList]:等等等等

expression[variablesList]: blah blah

但我怎么回归的值,以我原来的规则?例如。我该如何计算除权pression的值,然后发回给我分配规则在Python呢?

But how do I 'return' a value to my original rule? E.g. how do I calculate the value of the expression and then send it back to my assignment rule to use in Python there?

我怎样写我的目标语言code?

所以我有一些Python它运行时的规则被认可的话,我计算我想这句话生产组装。但我怎么说的装配说明这串写出来我的目标文件?

So I have some Python which runs when the rules are recognised, then I calculate the assembly I want that statement to produce. But how do I say "write out this string of assembly instructions to my target file"?

任何好的教程是相关的这种东西(属性语法,编译到比AST以外的东西等)将是有益的了。如果我的问题没有什么太大的意义,请让我澄清;我有一个很难包装我身边ANTLR头。

Any good tutorials that are relevant to this kind of stuff (attribute grammars, compiling to something other than an AST, etc.) would be helpful too. If my questions don't make too much sense, please ask me to clarify; I'm having a hard time wrapping my head around ANTLR.

推荐答案


假设你想简单的解析前pressions并能够在这些前pressions使用运行时提供地图变量。一个简单的语法,包括自定义的Python code,从规则返回语句和参数瓦尔来的你的语法的入口点可能是这样的:

Let's say you want to parse simple expressions and provide a map of variables at runtime that can be used in these expressions. A simple grammar including the custom Python code, returns statements from the rules, and the parameter vars to the entry point of your grammar could look like this:

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};

如果你现在使用ANTLR v3.1.3生成一个解析器(不迟版本!):

If you now generate a parser using ANTLR v3.1.3 (no later version!):

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}))

您将看到正在打印的输出如下:

you will see the following output being printed:

a + (1.0 + 2) * 3 = 51.0

请注意,您可以定义多单回型:

Note that you can define more than a single "return" type:

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}
  ;



去这个最简单的是简单地把打印自定义code块和管道输出到一个文件中的语句:

The easiest to go about this is to simply put print statements inside the custom code blocks and pipe the output to a file:

parse_with [vars]
@init{self.variables = vars}
  :  expression EOF                            {print 'OUT:', $expression.value}
  ;

然后像这样运行脚本:

and then run the script like this:

./run.py > out.txt

这将创建一个文件out.txt载: OUT:51.0 。如果你的语法并不大,你可能会逃脱这一点。然而,这可能成为一个有点乱,在这种情况下,您可以将您的解析器的输出设置为模板

which will create a file 'out.txt' containing: OUT: 51.0. If your grammar isn't that big, you might get away with this. However, this might become a bit messy, in which case you could set the output of your parser to template:

options {
  output=template;
  language=Python;
}

和通过自己定义的模板发出定制code。

and emit custom code through your own defined templates.

请参阅:

  • StringTemplate: 5 minute Introduction
  • Where to get Python ANTLR package to use StringTemplate?

这篇关于两个基本的ANTLR问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆