antlr4 代码 语法树
DSL是很酷的东西,但我不清楚它们有什么用。
然后我意识到它们对以下方面有好处:
- 摆脱复杂的UI
意思是
- 更快的做事方式
而已。 当我阅读此博客时,我得出了这个结论。
如果您的用户是技术人员,并且不惧怕类似SQL的语法处理方式,则DSL特别适合
- 你有语法高亮
- 你有代码补全
否则,DSL有点烂。
因此,我不得不向客户提出一些概念证明。 他有模糊的要求,要准确提取团队的需求并不容易(他们需要很多东西,而且他很忙),因此DSL可以在此过程中提供很多帮助,因为人们被迫在他们需要时才想清楚他们的需求面对一种语法(甚至很小的一种)。
因此,我采用了以下技术:
- 用于代码镜像的JSF库Primefaces扩展
- ANTLR4 (与ANTLR3相比有很大的改进,而且本书很棒)
不幸的是,我无法在两个工具中重复使用语法。 实际上,我找不到任何可以做到这一点的解决方案。 至少对于基于Web的JSF解决方案。 而且没有时间学习。 所以我不得不稍微改一下。
首先,我们需要语法。 ANTLR4比ANTLR3更好,因为现在接线代码是通过访问者和侦听器完成的。 语法内没有更多的Java代码。 那很棒,而且更容易使用。
所以你可以有一个这样的语法
grammar Grammar;
options
{
language = Java;
}
@lexer::header {
package parsers;
}
@parser::header {
package parsers;
}
eval : expr EOF;
expr : 'JOB' (jobName)? type 'TARGET' targetList ('START' startExpr)?
startExpr
: 'AT' cronTerm
| 'AFTER' timeAmount timeUnits;
timeAmount: INT;
jobName: STRING;
targetList: STRING (',' STRING)*;
type : deleteUser
| createUser;
deleteUser: opDelete userName;
createUser: opCreate userName;
opDelete: 'DELETE';
opCreate: 'CREATE';
userName: STRING;
cronTerm: '!'? (INT | '-' | '/' | '*' | '>' | '<')+;
timeUnits
: 'MINUTES'
| 'HOURS'
| 'DAYS'
| 'WEEKS'
| 'MONTHS';
WS : [ \t\r\n]+ -> skip;
STRING
: '"' ( ESC_SEQ | ~('\\'|'"') )* '"'
;
fragment
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;
fragment
ESC_SEQ
: '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
| UNICODE_ESC
| OCTAL_ESC
;
fragment
OCTAL_ESC
: '\\' ('0'..'3') ('0'..'7') ('0'..'7')
| '\\' ('0'..'7') ('0'..'7')
| '\\' ('0'..'7')
;
fragment
UNICODE_ESC
: '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
;
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
;
INT : '0'..'9'+
;
要编译语法,请尝试
public static void main(String[] args) {
String[] arg0 = {"-visitor","/pathto/Grammar.g4"};
org.antlr.v4.Tool.main(arg0);
}
然后,ANTLR将为您生成类。
在我们的例子中,我们想访问解析树并检索我们想要的值。 我们这样做扩展了生成的抽象类。
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.antlr.v4.runtime.tree.ErrorNode;
import bsh.EvalError;
import bsh.Interpreter;
public class MyLoader2 extends GrammarBaseVisitor<Void> {
private String jobName,cronTerm,timeUnits,userName,jobType;
private List<String> targetList;
private boolean now,errorFound;
private int timeAmount;