我试图创建一个解析器,它可以将英文句子转换为画布上的绘制形状。例如: “创建一个红色框”应该在画布上创建一个红色的框。
我从你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();}
;
然后我用这段代码生成词法分析器和解析器。我下一步要做什么。我如何使用解析器,例如将“创建”转换为对象的创建。有人能指出我正确的方向吗?
答案 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。它清楚地描述了如何进行。
我希望这会有所帮助。