ANTLR的基本帮助

时间:2011-05-11 17:58:10

标签: java antlr parser-generator

我试图创建一个解析器,它可以将英文句子转换为画布上的绘制形状。例如: “创建一个红色框”应该在画布上创建一个红色的框。

我从你wiki的教程中得到了这个语法文件。不知道它是否正确,如果有人可以检查它会很好=)

grammar Shrdlu;

tokens {

    //operational tokens
    MOVE        = 'move';
    TRANSFORM   = 'transform';
    CREATE      = 'create';
    MAKE        = 'make';
    ADD         = 'add';
    REMOVE      = 'remove';
    DELETE      = 'delete';

    //shape tokens
    BOX         = 'box';
    RECTANGLE   = 'rectangel';
    CIRCLE      = 'circle';
    TRIANGLE    = 'triangle';
    SHAPE       = 'shape';
    SQUARE      = 'square';

    //color tokens
    RED         = 'red';
    BLUE        = 'blue';
    GREEN       = 'green';
    BLACK       = 'black';
    PURPLE      = 'purple';
    YELLOW      = 'yellow';
    ORANGE      = 'orange';
    PINK        = 'pink';

    //size tokens
    BIG         = 'big';
    LARGE       = 'large';
    TALL        = 'tall';
    SMALL       = 'small';
    TINY        = 'tiny';
    SHORT       = 'short';

    //relation size
    BIGGEST     = 'biggest';
    LARGEST     = 'largest';
    TALLEST     = 'tallest';
    SMALLEST    = 'smallest';   
    SHORTEST    = 'shortest';

    //argument size
    BIGGER      = 'bigger';
    SMALLER     = 'smaller';
    SHORTER     = 'shorter';
    TALLER      = 'taller';
    LARGER      = 'larger';

    //alignment tokens
    LEFT        = 'left';
    RIGHT       = 'right';
    OVER        = 'over';
    UNDER       = 'under';
    ABOVE       = 'above';
    BELOW       = 'below';
    TOP         = 'top';
    BOTTOM      = 'bottom';

    //prefix tokens
    A           = 'a';
    AN          = 'an';
    ALL         = 'all';
    ANY         = 'any';
    EACH        = 'each';
    THE         = 'the';

}

/*------------------------------------------------------------------
 * PARSER RULES
 *------------------------------------------------------------------*/

command
    :   sentence EOF
    |
    ;

sentence
    :   WS? action WS object (WS argument)? WS?
    ;

action

    :   MOVE
    |   TRANSFORM
    |   CREATE
    |   MAKE
    |   ADD
    |   REMOVE
    |   DELETE
    ;

object
    :   prefix WS (property WS)?  shape (WS relation WS object)?
    ;

a    rgument
    :   color
    |   sizearg
    |   alignment
    ;

prefix
    :   A
    |   AN
    |   ALL
    |   ANY
    |   EACH
    |   THE
    ;

shape
    :   BOX
    |   RECTANGLE
    |   CIRCLE
    |   TRIANGLE
    |   SHAPE
    |   SQUARE
    ;

property
    :   size (WS property)?
    |   color (WS property)?
    ;


size
    :   BIG
    |   LARGE
    |   TALL
    |   SMALL
    |   TINY
    |   SHORT
    ;

sizearg
    :   BIGGER
    |   LARGER
    |   SMALLER
    |   TALLER
    |   SHORTER 
    ;

relsize
    :   BIGGEST
    |   SMALLEST
    |   TALLEST
    |   LARGEST
    ;   


relation
    :   alignment
    |   relsize
    ;

color
    :   RED
    |   BLUE
    |   GREEN
    |   BLACK
    |   PURPLE
    |   YELLOW
    |   ORANGE
    |   PINK
    ;

alignment
    :   LEFT
    |   RIGHT
    |   OVER
    |   UNDER
    |   ABOVE
    |   BELOW
    |   TOP
    |   BOTTOM
    ;

/*------------------------------------------------------------------
 * LEXER RULES
 *------------------------------------------------------------------*/

NEWLINE
    :   '\r'? '\n'
    ;

WS
    :   (' '|'\t'|'\n'|'\r')+ {skip();}
    ;

然后我用这段代码生成词法分析器和解析器。我下一步要做什么。我如何使用解析器,例如将“创建”转换为对象的创建。有人能指出我正确的方向吗?

2 个答案:

答案 0 :(得分:2)

由于{skip();}规则中的WS,您的词法分析器永远不会创建任何WS令牌。因此,WS规则中包含sentence的解析器规则永远不会匹配。所以从这个意义上来说,你的语法是错误的。

  

Richard写道:

     

创建一个对象。

修改

您可以为解析器提供自定义属性,例如您要绘制的Graphics对象(请参阅下面语法的@parser::members { ... }部分)。并在{}之间的语法规则中嵌入自定义代码。作为演示,我只添加了一些System.out.println,但你应该用你的实际绘画替换它们。我还从解析器规则中删除了WS令牌(另请注意,Create不等于create!)。

修改后的语法:

grammar Shrdlu;

tokens {

    //operational tokens
    MOVE        = 'move';
    TRANSFORM   = 'transform';
    CREATE      = 'create';
    MAKE        = 'make';
    ADD         = 'add';
    REMOVE      = 'remove';
    DELETE      = 'delete';

    //shape tokens
    BOX         = 'box';
    RECTANGLE   = 'rectangel';
    CIRCLE      = 'circle';
    TRIANGLE    = 'triangle';
    SHAPE       = 'shape';
    SQUARE      = 'square';

    //color tokens
    RED         = 'red';
    BLUE        = 'blue';
    GREEN       = 'green';
    BLACK       = 'black';
    PURPLE      = 'purple';
    YELLOW      = 'yellow';
    ORANGE      = 'orange';
    PINK        = 'pink';

    //size tokens
    BIG         = 'big';
    LARGE       = 'large';
    TALL        = 'tall';
    SMALL       = 'small';
    TINY        = 'tiny';
    SHORT       = 'short';

    //relation size
    BIGGEST     = 'biggest';
    LARGEST     = 'largest';
    TALLEST     = 'tallest';
    SMALLEST    = 'smallest';   
    SHORTEST    = 'shortest';

    //argument size
    BIGGER      = 'bigger';
    SMALLER     = 'smaller';
    SHORTER     = 'shorter';
    TALLER      = 'taller';
    LARGER      = 'larger';

    //alignment tokens
    LEFT        = 'left';
    RIGHT       = 'right';
    OVER        = 'over';
    UNDER       = 'under';
    ABOVE       = 'above';
    BELOW       = 'below';
    TOP         = 'top';
    BOTTOM      = 'bottom';

    //prefix tokens
    A           = 'a';
    AN          = 'an';
    ALL         = 'all';
    ANY         = 'any';
    EACH        = 'each';
    THE         = 'the';

}

@parser::members {

  private java.awt.Graphics graphics;

  public ShrdluParser(TokenStream tokens, java.awt.Graphics g) {
    super(tokens);
    graphics = g;
  }
}

/*------------------------------------------------------------------
 * PARSER RULES
 *------------------------------------------------------------------*/

command
    :   sentence EOF
    |
    ;

sentence
    :   action object argument?
    ;

action

    :   MOVE
    |   TRANSFORM
    |   CREATE    {System.out.println("I should create a ...");}
    |   MAKE
    |   ADD
    |   REMOVE
    |   DELETE
    ;

object
    :   prefix property?  shape (relation object)?
    ;

argument
    :   color
    |   sizearg
    |   alignment
    ;

prefix
    :   A
    |   AN
    |   ALL
    |   ANY
    |   EACH
    |   THE
    ;

shape
    :   BOX       {System.out.println("box ...");}
    |   RECTANGLE
    |   CIRCLE
    |   TRIANGLE
    |   SHAPE
    |   SQUARE
    ;

property
    :   size property?
    |   color property?
    ;


size
    :   BIG
    |   LARGE
    |   TALL
    |   SMALL
    |   TINY
    |   SHORT
    ;

sizearg
    :   BIGGER
    |   LARGER
    |   SMALLER
    |   TALLER
    |   SHORTER 
    ;

relsize
    :   BIGGEST
    |   SMALLEST
    |   TALLEST
    |   LARGEST
    ;   


relation
    :   alignment
    |   relsize
    ;

color
    :   RED   {System.out.println("red ...");}
    |   BLUE
    |   GREEN
    |   BLACK
    |   PURPLE
    |   YELLOW
    |   ORANGE
    |   PINK
    ;

alignment
    :   LEFT
    |   RIGHT
    |   OVER
    |   UNDER
    |   ABOVE
    |   BELOW
    |   TOP
    |   BOTTOM
    ;

NEWLINE
    :   '\r'? '\n'
    ;

WS
    :   (' '|'\t'|'\n'|'\r')+ {skip();}
    ;

可以在课堂上进行测试:

import org.antlr.runtime.*;

public class Main {
    public static void main(String[] args) throws Exception {
        ANTLRStringStream in = new ANTLRStringStream("create a red box");
        ShrdluLexer lexer = new ShrdluLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        java.awt.Graphics g = null;
        ShrdluParser parser = new ShrdluParser(tokens, g);
        parser.command();
    }
}

从语法中创建词法分析器和解析器:

java -cp antlr-3.3.jar org.antlr.Tool Shrdlu.g

然后编译所有.java源文件:

javac -cp antlr-3.3.jar *.java

并运行Main类:

# *nix
java -cp .:antlr-3.3.jar Main

# Windows
java -cp .;antlr-3.3.jar Main

产生以下输出:

I should create a ...
red ...
box ...

最后一件事,您可以删除NEWLINE规则:您的WS规则捕获此类字符(并忽略它们)。

答案 1 :(得分:0)

下一步应该是创建一个AST并让它在你找到节点时采取行动。

对我来说,解释如何继续这样做有点困难(但对我而言),但我强烈建议你购买由ANTRL作者撰写的这本书Language Implementation Patterns: Create Your Own Domain-Specific and General Programming Languages。它清楚地描述了如何进行。

我希望这会有所帮助。