antlr v4 使用指南连载5——如何编写词法定义
如何编写词法定义#
继上一篇文章,相信大家都明了编写词法规则的两个基本原则。那么接下来就可以开始编写词法文件了。对于计算机科学来说,很多词法规则是一致的。如标识符、数字等,它们都可以重复在多个项目中应用,这是题外话。
在词法文件中,除了词法定义之外,还有一些可选项,应该要先说明一下。匆匆一瞥,以览概貌,这是我一贯的风格。
fragment 词法片段,构成词法的元素,不是一个词法规则。在词法规则中可引用一个或多个词法片段。如:
fragement
DIGIT : [0-9];
INTEGER : DIGIT | [1-9] DIGIT+;
{action} 词法规则关联的目标语言代码。当输入串被词法规则匹配时,执行定义的action。如:
fragement
DIGIT : [0-9];
INTEGER : DIGIT | [1-9] DIGIT+ {System.out.println("match an integer.");};
mode 主要用于解决一个语法中包含一个或多个其他不同的语法。如Java语法的annotation(注解)。再比如XML文件,示例如下:
lexer grammar XMLLexer;
// Default "mode" : Everything OUTSIDE of a tag
OPEN : '<' ->pushMode(INSIDE);
COMMENT : '<!--'.*?'-->' ->skip;
EntityRef : '&'[a-z]+';';
TEXT : ~('<'|'&')+; //match any 16bit char minus < and &
// -----------------Everything INSIDE of a tag--------------------- mode INSIDE;
CLOSE : '>' ->popMode;//back to default mode
SLASH_CLOSE: '/>' ->popMode;
EQUALS : '=';
STRING : '"'.*?'"';
SlashName : '/'Name;
Name : ALPHA (ALPHA|DIGIT)*;
S : [\t\r\n] ->skip;
fragment
ALPHA : [a-zA-Z];
fragment
DIGIT : [0-9];
hidden channel 将不需要关注的如注释、空格等发送到隐藏通道中。当然需要的时候还可以用antlr的api获取回来。如:
COMMENT : '/*'.*?'*/' -> channel(HIDDEN); //match anything between /* and */
WS : [\r\t\u000C\n]+ -> channel(HIDDEN);
词法(lexer)文件中的所有内容已经清晰地介绍给大家了,下面正式进入词法规则编写。遵照antlr词法规则及惯例,在词法文件中,一般会将fragment、单字符定义、关键字定义放在最前面,而具体的词法(token)定义放在后面。
除此之外,还有一个一开始可能就要考虑的问题,就是你所编写的目标语言对大小写是否敏感。在这里我推荐的写法如下:
大小写敏感 对26个英文字母分别定义大写、小写两个词法规则。使用的时候大写地方就用大写的词法规则,小写就用小写的词法规则。
fragment
A : [A];
fragment
A_ : [a];
大小写不敏感 对26个字母定义一个词法规则,包含大小写字母在里面。使用的时候,直接使用词法规则代替。
fragment
A : [aA];
由此可见,词法文件的开头应该就是根据是否大小敏感先把26个英文字母的词法规则确定。然后就是定义关键字及预定义字符。关键字就是目标语言的保留、非保留关键字。保留关键字是指只允许在语言规范定义的地方使用,不能在其他地方使用;非保留关键字是指可以使用,但不推荐使用。预定义字符是指诸如操作符(>, <, =, >>, >>>, >=, <=, ., ^, %, $, @, !, *, +, -等)。紧接着就可以定义其他fragment了,如DIGIT。fragment就是定义一些不需要被识别为独立token的字符,如0-9,定义一个fragment给其他词法规则引用,而0-9本身可以另外定义一个整数的词法规则来匹配。下面是sqlite的示例:
fragment DIGIT : [0-9];
fragment A : [aA];
fragment B : [bB];
fragment C : [cC];
fragment D : [dD];
fragment E : [eE];
fragment F : [fF];
fragment G : [gG];
fragment H : [hH];
fragment I : [iI];
fragment J : [jJ];
fragment K : [kK];
fragment L : [lL];
fragment M : [mM];
fragment N : [nN];
fragment O : [oO];
fragment P : [pP];
fragment Q : [qQ];
fragment R : [rR];
fragment S : [sS];
fragment T : [tT];
fragment U : [uU];
fragment V : [vV];
fragment W : [wW];
fragment X : [xX];
fragment Y : [yY];
fragment Z : [zZ];
SCOL : ';';
DOT : '.';
OPEN_PAR : '(';
CLOSE_PAR : ')';
COMMA : ',';
ASSIGN : '=';
STAR : '*';
PLUS : '+';
MINUS : '-';
TILDE : '~';
PIPE2 : '||';
DIV : '/';
MOD : '%';
LT2 : '<<';
GT2 : '>>';
AMP : '&';
PIPE : '|';
LT : '<';
LT_EQ : '<=';
GT : '>';
GT_EQ : '>=';
EQ : '==';
NOT_EQ1 : '!=';
NOT_EQ2 : '<>';
// http://www.sqlite.org/lang_keywords.html
K_ABORT : A B O R T;
K_ACTION : A C T I O N;
K_ADD : A D D;
K_AFTER : A F T E R;
K_ALL : A L L;
K_ALTER : A L T E R;
K_ANALYZE : A N A L Y Z E;
K_AND : A N D;
K_AS : A S;
K_ASC : A S C;
K_ATTACH : A T T A C H;
K_AUTOINCREMENT : A U T O I N C R E M E N T;
K_BEFORE : B E F O R E;
K_BEGIN : B E G I N;
K_BETWEEN : B E T W E E N;
K_BY : B Y;
K_CASCADE : C A S C A D E;
K_CASE : C A S E;
K_CAST : C A S T;
K_CHECK : C H E C K;
K_COLLATE : C O L L A T E;
K_COLUMN : C O L U M N;
K_COMMIT : C O M M I T;
K_CONFLICT : C O N F L I C T;
K_CONSTRAINT : C O N S T R A I N T;
K_CREATE : C R E A T E;
K_CROSS : C R O S S;
K_CURRENT_DATE : C U R R E N T '_' D A T E;
K_CURRENT_TIME : C U R R E N T '_' T I M E;
K_CURRENT_TIMESTAMP : C U R R E N T '_' T I M E S T A M P;
K_DATABASE : D A T A B A S E;
K_DEFAULT : D E F A U L T;
K_DEFERRABLE : D E F E R R A B L E;
K_DEFERRED : D E F E R R E D;
K_DELETE : D E L E T E;
K_DESC : D E S C;
K_DETACH : D E T A C H;
K_DISTINCT : D I S T I N C T;
K_DROP : D R O P;
K_EACH : E A C H;
K_ELSE : E L S E;
K_END : E N D;
K_ESCAPE : E S C A P E;
K_EXCEPT : E X C E P T;
K_EXCLUSIVE : E X C L U S I V E;
K_EXISTS : E X I S T S;
K_EXPLAIN : E X P L A I N;
K_FAIL : F A I L;
K_FOR : F O R;
K_FOREIGN : F O R E I G N;
K_FROM : F R O M;
K_FULL : F U L L;
K_GLOB : G L O B;
K_GROUP : G R O U P;
K_HAVING : H A V I N G;
K_IF : I F;
K_IGNORE : I G N O R E;
K_IMMEDIATE : I M M E D I A T E;
K_IN : I N;
K_INDEX : I N D E X;
K_INDEXED : I N D E X E D;
K_INITIALLY : I N I T I A L L Y;
K_INNER : I N N E R;
K_INSERT : I N S E R T;
K_INSTEAD : I N S T E A D;
K_INTERSECT : I N T E R S E C T;
K_INTO : I N T O;
K_IS : I S;
K_ISNULL : I S N U L L;
K_JOIN : J O I N;
K_KEY : K E Y;
K_LEFT : L E F T;
K_LIKE : L I K E;
K_LIMIT : L I M I T;
K_MATCH : M A T C H;
K_NATURAL : N A T U R A L;
K_NO : N O;
K_NOT : N O T;
K_NOTNULL : N O T N U L L;
K_NULL : N U L L;
K_OF : O F;
K_OFFSET : O F F S E T;
K_ON : O N;
K_OR : O R;
K_ORDER : O R D E R;
K_OUTER : O U T E R;
K_PLAN : P L A N;
K_PRAGMA : P R A G M A;
K_PRIMARY : P R I M A R Y;
K_QUERY : Q U E R Y;
K_RAISE : R A I S E;
K_RECURSIVE : R E C U R S I V E;
K_REFERENCES : R E F E R E N C E S;
K_REGEXP : R E G E X P;
K_REINDEX : R E I N D E X;
K_RELEASE : R E L E A S E;
K_RENAME : R E N A M E;
K_REPLACE : R E P L A C E;
K_RESTRICT : R E S T R I C T;
K_RIGHT : R I G H T;
K_ROLLBACK : R O L L B A C K;
K_ROW : R O W;
K_SAVEPOINT : S A V E P O I N T;
K_SELECT : S E L E C T;
K_SET : S E T;
K_TABLE : T A B L E;
K_TEMP : T E M P;
K_TEMPORARY : T E M P O R A R Y;
K_THEN : T H E N;
K_TO : T O;
K_TRANSACTION : T R A N S A C T I O N;
K_TRIGGER : T R I G G E R;
K_UNION : U N I O N;
K_UNIQUE : U N I Q U E;
K_UPDATE : U P D A T E;
K_USING : U S I N G;
K_VACUUM : V A C U U M;
K_VALUES : V A L U E S;
K_VIEW : V I E W;
K_VIRTUAL : V I R T U A L;
K_WHEN : W H E N;
K_WHERE : W H E R E;
K_WITH : W I T H;
K_WITHOUT : W I T H O U T;
IDENTIFIER
: '"' (~'"' | '""')* '"'
| '`' (~'`' | '``')* '`'
| '[' ~']'* ']'
| [a-zA-Z_] [a-zA-Z_0-9]* // TODO check: needs more chars in set
;
NUMERIC_LITERAL
: DIGIT+ ( '.' DIGIT* )? ( E [-+]? DIGIT+ )?
| '.' DIGIT+ ( E [-+]? DIGIT+ )?
;
BIND_PARAMETER
: '?' DIGIT*
| [:@$] IDENTIFIER
;
STRING_LITERAL
: '\'' ( ~'\'' | '\'\'' )* '\''
;
BLOB_LITERAL
: X STRING_LITERAL
;
SINGLE_LINE_COMMENT
: '--' ~[\r\n]* -> channel(HIDDEN)
;
MULTILINE_COMMENT
: '/*' .*? ( '*/' | EOF ) -> channel(HIDDEN)
;
SPACES
: [ \u000B\t\r\n] -> channel(HIDDEN)
;
词法规则的写法就介绍到这里为止。
未完待续>>>
antlr v4 使用指南连载5——如何编写词法定义的更多相关文章
- antlr v4 使用指南连载2——准备环境
antlr v4 开发环境 从上一篇文章的例子中可以知道,antlr有一套自己的语法来声明目标语言的语法,因此它本身就需要编译或者使用antlr提供的api来读取这些语法规则,并使之可 ...
- antlr v4 使用指南连载1——简介
antlr v4简介 antlr是一个强大语言解析工具,可以用于处理结构化文本.二进制文件.说白了,其实可以这么认为,antlr是一个更强大的正则表达式工具.它可以完成更多正则表达式无法 ...
- antlr v4 使用指南连载3——g4文件概览
g4文件概览 在深入介绍之前,有必要先给大家了解一下g4文件的结构,以便对如何编写语法规则文件有个全局的认识,我想这是大有禆益的.因为这样我们就可以很清晰地知道需要的东西写在哪里,或者哪 ...
- antlr v4 使用指南连载4——词法规则入门之黄金定律
词法规则入门 黄金定律一二 若输入串能被多个词法规则匹配,那么声明在词法文件最前面的规则生效. parser parser grammar HelloParser; options { languag ...
- Antlr v4入门教程和实例
1 重逢ANTLR 最早知道ANTLR是当年学习Apache Derby数据库源码时,在看到SQL解析那一层时,第一次看到编译原理在实际项目中的应用,惊叹之余也只能望而却步.之前也根据网上一些资料尝试 ...
- ANTLR v4 权威参考笔记(目录)
ANTLR v4是一款强大的语法分析器生成器,可以用来读取.处理.执行和转换结构化文本或二进制文件.通过称为文法的形式化语言描述,ANTLR可以为该语言自动生成词法分析器.生成的语法分析器可以自动构建 ...
- Robot Framework自动化测试框架核心指南-如何使用Java编写自定义的RobotFramework Lib
如何使用Java编写自定义的RobotFramework Lib 本文包括2个章节 1. Robot Frdamwork中如何调用java Lib库 2.使用 java编写自定义的Lib 本文作者为: ...
- Android Cordova 插件开发之编写自己定义插件
前言 本文适合Android+web的复合型人才,由于cordova本身就是混合开发,所以在Android开发的基础上,还要懂web相关技术(HTML+CSS+JS).可是也有例外,比方我.仅仅需负责 ...
- QTP自动化测试权威指南 连载(一)
第一章 简介 什么是自动化测试 自动化测试是对一个已有的手工测试过程减少并尽可能排除人工干预的过程. 什么时候适合做自动化测试 下面是一组适合将手工测试自动化的考量因素: ● 测试需要经常重复. ● ...
随机推荐
- 【Noip2017游记】
好像是考Noip的第5个年头了...高中的第一次Noip... 考了三年PJ,今年是第二次TG,希望不要像去年那么萎(gou) Day -1 考前停课了挺久的来着的,学长出了N套题来模拟,自己练了DP ...
- bzoj 5297: [Cqoi2018]社交网络
Description 当今社会,在社交网络上看朋友的消息已经成为许多人生活的一部分.通常,一个用户在社交网络上发布一条消息 (例如微博.状态.Tweet等)后,他的好友们也可以看见这条消息,并可能转 ...
- bzoj 1085: [SCOI2005]骑士精神
Description 在一个5×5的棋盘上有12个白色的骑士和12个黑色的骑士,且有一个空位.在任何时候一个骑士都能按照骑士的走法(它可以走到和它横坐标相差为1,纵坐标相差为2或者横坐标相差为2,纵 ...
- bzoj1877
1877: [SDOI2009]晨跑 Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 2660 Solved: 1424[Submit][Status][ ...
- 将 Hexo 个人博客同时部署到 GitHub 和 Coding 上
一.将个人博客托管到 GitHub 上 关于如何快速搭建自己的个人博客,如何完善自己的个人博客,什么是 GitHub ,如何将自己的博客代码托管到 GitHub 上面等等问题,我之前写过三篇文章已经做 ...
- 如何使用 TeamViewer 配置QuickConnect按钮?
QuickConnect作为TeamViewer中一个比较重要的部分,得到了很多用户的认可.那么在实际运用中,怎么才能设置网页或单个程序的QuickConnect呢?所以小编以此问题为例,教大家如何配 ...
- google-gson 解析json
http://www.cnblogs.com/jianyungsun/p/6647203.html 在JSON官网我们可以查看到各个语法对json的支持,对于java来说比较成熟的是google-gs ...
- 利用Express模拟web安全之---xss的攻与防
一.什么是XSS? 跨站脚本攻击(Cross Site Scripting),为了不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS.恶意 ...
- Docker学习系列(一)Docker简介
简介 Docker是一个在全球范围领先的软件容器平台.开发人员可以使用容器来在协作过程中遇到的解决"不同环境配置"的问题.(例如,在传统的开发环境下,开发人员编写代码,然后交由测试 ...
- 05_CRUD操作
1.Params拦截器: 作用:Parameters拦截器将把表单字段映射到ValueStack栈的栈顶对象的各个属性中, 注意:如果某个字段在栈顶对象中没有对应的属性,则Params拦截器将尝试 ...