Основная помощь с ANTLR - PullRequest
0 голосов
/ 11 мая 2011

Я пытаюсь создать парсер, который мог бы переводить английские предложения в нарисованные фигуры на холсте.Например: «Создать красное поле» должно создать поле на холсте красного цвета.

Я нашел этот файл грамматики из учебника в вашей вики.Не знаю, если это правильно, было бы хорошо, если бы кто-то мог проверить это =)

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

Затем я использовал этот код для генерации лексера и парсера.Каков мой следующий шаг.Как использовать синтаксический анализатор, например, transalte «создать» в создании объекта.Может ли кто-нибудь указать мне правильное направление?

Ответы [ 2 ]

2 голосов
/ 11 мая 2011

Из-за {skip();} в правиле WS ваш лексер никогда не будет создавать никаких WS токенов.Таким образом, правила синтаксического анализа, содержащие WS, например, правило sentence, никогда не будут совпадать.Так что в этом смысле ваша грамматика неверна.

Ричард писал:

в создании объекта.

РЕДАКТИРОВАТЬ

Вы можете присвоить своему синтаксическому анализатору пользовательские атрибуты, например, объект 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ловит такие символы (и игнорирует их).

0 голосов
/ 11 мая 2011

Следующим шагом должно быть создание AST и его выполнение для выполнения действий при поиске узлов.

М-м-м-м, мне немного сложно объяснить, как это сделать, но я настоятельно рекомендую вам купить эту книгу Шаблоны языковой реализации: создайте свое собственное доменное и общее программированиеЯзыки написаны автором ANTRL.Он четко описывает, как действовать.

Надеюсь, это поможет.

...