这部分代码是需要动态生成的,语法分析
perl复制代码"compile-antlr-windows": "@powershell -NoProfile -ExecutionPolicy Unrestricted -Command ./compile-antlr.ps1",
javascript复制代码Set-Location "syntaxes" Remove-Item "../src/_generated" -Recurse -ErrorAction Ignore npx antlr4ts -o "../src/_generated" "AntlrGlslLexer.g4" npx antlr4ts -o "../src/_generated" -no-listener -visitor "AntlrGlslParser.g4"
ANTLR是基于LL算法实现的语法解析器生成器
源码分析
当插件启动后就会分析诊断当前打开的文档内容,根据antlr的ast抽象语法树,对整个代码进行分析
"Open documentation"
当鼠标hover后,语法接下内容后,判断当前鼠标处的内容是什么,变量函数?然后查找对应的hover提示内容,
一切的基础都是那个antlr
bash复制代码antlr4ts -o ./src/antlr -no-listener -visitor ./syntaxes/CocosEffect.g4
vbnet复制代码ANTLR Parser Generator Version 4.9.0-SNAPSHOT -o ___ specify output directory where all output is generated -no-listener don't generate parse tree listener -visitor generate parse tree visitor
语法遍历解释
g4复制代码grammar CocosEffect; prog: (expr NEWLINE)* ; expr: expr ('*'|'/') expr | expr ('+'|'-') expr | INT | '(' expr ')' ; NEWLINE : [\r\n]+ ; INT : [0-9]+ ;
antrl生成的ts visitor有对应的回调接口,当检测到文本符合对应的语法时,就会触发对应语法的ts回调接口,举个例子
antlr生成的Visitor代码如下
ts复制代码export interface CocosEffectVisitor<Result> extends ParseTreeVisitor<Result> { // 这2个都是语法接口,对应g4里面写的语法key,数据类型是grammar key + Context visitProg?: (ctx: ProgContext) => Result; visitExpr?: (ctx: ExprContext) => Result; }
我们只需要继承antlr的Visitor,然后重写对应的回调,即可拿到分析后的结果
ts复制代码export class Visitor extends AbstractParseTreeVisitor<void> implements CocosEffectVisitor<void> { visitExpr(ctx: ExprContext): void { // 编写自己的处理语法逻辑 return; } }
注意java version
antlr grammar syntax support插件主要是语法着色,安装后output窗口有报错
csharp复制代码Running Java with parameters: -jar antlr4ng-cli\antlr4-4.13.2-SNAPSHOT-complete.jar -message-format antlr -o e:\proj\cocos-effect\syntaxes\.antlr -no-listener -no-visitor -Xexact-output-dir e:\proj\cocos-effect\syntaxes\CocosEffect.g4 Exception in thread "main" java.lang.UnsupportedClassVersionError: org/antlr/v4/Tool has been compiled by a more recent version of the Java Runtime (class file version 55.0), this version of the Java Runtime only recognizes class file versions up to 52.0
java8是52, java11是55,切换到java11就正常,发现的确是跟java版本有关系,我用的是java8,切换本机java环境就正常了。
parse tree inspector
这个功能是antlr的jar包自带的,而justAntlr插件提供了grammar tree inpsepctor的快捷操作。
但是我一直没有成功,翻了下源码,终于了解到了细节:
在选择文件后,执行的java命令,所以这个要求java版本也得匹配,不然还会报上边的错误
会在cwd目录生成对应的解析器java代码:
同时还有警告信息:
vbnet复制代码This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason: extensionHostProcess.js:108 No method for rule -gui or it has arguments
使用命令行我尝试了,只有最后一行的日志信息,查看了下用法,最开始其实我没有认为这是命令行的一部分,主要是因为java的命令行内容太长了
ini复制代码E:\proj\cocos-effect\syntaxes\.gen\CSV>java -cp .;F:\proj\justAntlr\lib\antlr-4.10.1-complete.jar org.antlr.v4.gui.TestRig -h java org.antlr.v4.gui.TestRig GrammarName startRuleName ↑ 包含功能的jar包 ↑ 语法名字 ↑从哪个规则开始 [-tokens] [-tree] [-gui] [-ps file.ps] [-encoding encodingname] [-trace] [-diagnostics] [-SLL] [input-filename(s)] Use startRuleName='tokens' if GrammarName is a lexer grammar. Omitting input-filename makes rig read from stdin.
再次看了下输入的命令
java -cp 是 Java 命令的一部分,用于指定类路径(class path),这个是java的基础知识,注意这里的.;,是因为编译需要找到antlr生成的那些代码。
bash复制代码java -cp .;F:\proj\justAntlr\lib\antlr-4.10.1-complete.jar org.antlr.v4.gui.TestRig CSV # GrammarName -gui C:\Users\Administrator\Desktop\effect\1.csv # input-filename
看了很久,找了很多资料,才发现命令行里面缺少了startRuleName,翻了下justAntlr源码,它是通过鼠标选中的内容来确定startRuleName参数,gif中其实有这个操作,不注意真的看不出来的,而且文档里面也没有说明这点。
终于出来了,在这个tree上浪费了太多的时间。
startRuleName
这个参数其实是告诉antlr,从哪个规则开始解析,对应的代码中我们也要调用生成规则函数来完成解析,这些都算是antlr的基础概念,建议还是从命令行使用antlr,能够更加透彻的理解。