删帖吧
本帖最后由 xyfree 于 2012-01-21 03:38 编辑滚
开始使用ANTLRWorks 编写词法规则
开始使用ANTLRWorks 编写词法规则为了让大家能够对ANTLRWorks有全过程的了解,也为了推广一下自己的Cx语言,我就用Cx语言来做例子了。
因为Cx语言跟C/C++是非常相像的,
所以我一开始的时候,脑子中先有Cx程序代码的模样,
然后再从代码示例中在脑子中构想词语的意义,这样语法规则自然就出来了。
虽然从Terence Parr(ANTLR的作者)的布局来看,(我猜)他是先从语法规则着手,逐步下降到词法规则,但我觉得先从词法规则开始比较适合新手。
废话少说,先来两段Cx语言里面注释的词法规则。
-------------------------------------------------------------------
/* Cx代码中忽略不去理会的字符,空白,tab,换行
不要在ANTLR中使用中文的注释。。有时候你可能会遇到莫名其妙的错误
*/
WHITESPACE
: (' ' | '\t' | '\n' | '\r'){ skip(); };
/*Cx中,块注释以两个连续的#开头,中间匹配0个或多个其他字符,直到遇见另外的连续两个#
*/
COMMENT
: '##' (.)* '##'{ skip(); };
/* Cx中行注释和在C++中的一样,中间匹配0个或多个 不是换行符的任意字符,直到遇到换行符结束行注释
如果行注释是在程序的末尾,后面可以没有换行符
*/
LINE_COMMENT
: '//' ~('\n'|'\r')*('\r\n' | '\r' | '\n') { skip(); }
| '//' ~('\n'|'\r')* { skip(); }
;
--------------------------------------------------------------------
在ANTLR中规定,词法规则名必须要以大写字母开头,通常是全大写字母。
按照惯例,只有开头是大写字母的词法规则是 fragment Lexer Rule,这样的词法规则是不会出现在parse tree中的(就是说不可以成为独立的parse tree节点)
譬如下面的例子展示如何使用fragment Lexer rule 来简化词法规则的编写
--------------------------------------------------------------------
/*十进制数字,由0至9十种字符组成,因为0..9在任何字符编码中都是连续的,所以可以用“..”
记得不要漏了单引号(双引号似乎也是可以的)
*/
fragment
DecimalDigit
: ('0'..'9');
//Cx语言里面的十进制数字面量参考了D语言里面的做法,允许使用下划线分隔开一个或多个数字串,具有更好的可读性
fragment
DecimalFragment
: DecimalDigit+( '_' DecimalDigit+)*;
//各种十进制整数的字面量,要用后缀来告诉编译器应该解释成什么样的基本类型
DECIMAL_UBYTE
: DecimalFragment ('ub'| 'UB');
DECIMAL_BYTE
: DecimalFragment ('b'| 'B');
DECIMAL_USHORT
: DecimalFragment ('us'| 'US');
DECIMAL_SHORT
: DecimalFragment ('s'| 'S');
DECIMAL_UINT
: DecimalFragment ('u'| 'U');
DECIMAL_INT
: DecimalFragment;
DECIMAL_LONG
: DecimalFragment ('l'| 'L');
DECIMAL_ULONG
: DecimalFragment ('ul'| 'UL');
--------------------------------------------------------------------
声明Cx语言的关键字
声明关键字通常比较简单,只需把整个关键字用引号括起来就可以了
这里有一个关于关键字词法规则的策略:
尽量不要在语法规则中出现单引号(也就是没有命名的词法规则),虽然这是可以的。
但是对于新手来说,因为自己对整个要编译的语言才概念并不是一下子就会很清晰,有时候你不得不更改关键字的规则。
如果语法规则中全是单引号,查找和替换你会觉得这是一个噩梦.....
所以尽量为词法字符编写词法规则。以下是Cx语言里面的词法规则的一些片段,没兴趣的可以忽略
---------------------------------------------------------------------
STATIC_KW
: 'static';
PUBLIC_KW
: 'public';
PROTECTED_KW
: 'protected';
PRIVATE_KW
: 'private';
DEFAULT_KW
: 'default';
// primitive pointers
CONSTRUCTOR_KW
: 'This';
DESTRUCTOR_KW
: '~This';
SELFREF_KW
: 'this';
THAT_KW
: 'that';
THERE_KW
: 'there';
NEW_KW
: 'new';
DELETE_KW
: 'delete';
SIZEOF_KW
: 'sizeof';
// flow control
IF_KW
: 'if';
ELSE_KW
: 'else';
SWITCH_KW
: 'switch';
CASE_KW
: 'case';
//中间省略很多很多多。。。
RBRACKET
: ']';
LBRACE
: '{';
RBRACE
: '}';
LTP
: '<#';
RTP
: '#>';
--------------------------------------------------------------
[ 本帖最后由 xyfree 于 2009-12-29 21:48 编辑 ]
页:
[1]