目录:
- 使用antlr4, 用ts/js还原protobuf生成的java代码为pb (一)
- 使用antlr4, 用ts/js还原protobuf生成的java代码为pb (二)
- 使用antlr4, 用ts/js还原protobuf生成的java代码为pb (三)
- 使用antlr4, 用ts/js还原protobuf生成的java代码为pb (四)
- 使用antlr4, 用ts/js还原protobuf生成的java代码为pb (五)
简介: 暂无
antlr: 暂无
优势: 暂无
背景:
- 使用正则我可以轻易完成任务, 但是我希望能有自我提升. 其次正则表达式很难处理递归匹配(虽然支持, 但是一点也不灵活).
- 是否可以选择mps. mps很优秀. 我还没看懂mps的处理过程. 对文本ast不友好
- 使用php实现javacc, 在实现lookahead时,遇到困难. 当语法存在二义性时,就需要向前预测该走哪个分支以解决二义性. 用php实现时, 判断条件过多, 实现太难(虽然写了不少代码了)
- antlr 可以解析java成ast, antlr4 比antlr3 更简单
- ts/js是我的第二语言, 虽然也有antlr php 的实现, 现在似乎缺乏antlr4 php runtime
- typescript提示更优越, 而且我更熟悉ts/es6
开发环境搭建
package.json
{
"name": "antlr_java",
"version": "1.0.0",
"description": "use antlr4ts or antlr4 to parse java, purpose to get pb from specify java class",
"author": "",
"license": "ISC",
"dependencies": {
"antlr4": "^4.6.0",
"antlr4ts": "^0.4.0-alpha.4"
}
}
tsconfig.json
{
"version": "2.1.4",
"compilerOptions": {
"target": "es6",
"declaration": true,
"module": "commonjs",
"moduleResolution": "node",
"sourceMap": true,
"emitDecoratorMetadata": false,
"experimentalDecorators": true,
"lib": [
"es2015",
"dom"
],
"removeComments": false,
"noImplicitAny": false,
"sourceRoot": "src/",
"outDir": "dist/",
"compileOnSave": true,
"types": [
"jasmine",
"node"
]
},
"include": [
"./src/**/*"
],
"exclude": [
"node_modules/*",
"compiled/*"
]
}
好了, 看到上面应该知道我们用的是最新的支持es6的nodejs.
安装antlr4ts
到全局
npm i -g antlr4ts
webstorm 配置 (用idea或其他jetbrain的ide也是可以的)
在typescript service 的options里设置 或者 打开Enable Typescript Compiler -> set options manually
--project "./tsconfig.json"
为什么要用antlr4ts, 而不是直接用antlr. 事实上antlr4ts只是antlr的ts运行时实现, antlr4默认支持 java, c#, go, python等运行时. 也就是我们可以用其他语言解析grammar. 但是生成其他语言的lexer, parser等需要antlr4 tool (这是由java写的)
首先实现基本的antlr示例以来测试环境是否正常
在src/antlr
目录中新建
Hello.g4
grammar Hello;
r : 'hello' ID;
ID : [a-z]+ ;
WS : [ \t\r\n]+ -> skip ;
如果你学过正则表达式, 那么你将很容易的学会antlr的grammar
grammar的详细解释可以查看the definitive antlr 4 reference图书
现在你在控制台输入如下命令
antlr4ts ./src/antlr/Hello.g4
antlr4ts与antlr4命令基本一致具体可通过
antlr4ts
或antlr4
查看ANTLR Parser Generator Version 4.6-SNAPSHOT
-o ___ specify output directory where all output is generated
-lib ___ specify location of grammars, tokens files
-atn generate rule augmented transition network diagrams
-encoding ___ specify grammar file encoding; e.g., euc-jp
-message-format ___ specify output style for messages in antlr, gnu, vs2005
-long-messages show exception details when available for errors and warnings
-listener generate parse tree listener (default)
-no-listener don't generate parse tree listener
-visitor generate parse tree visitor
-no-visitor don't generate parse tree visitor (default)
-package ___ specify a package/namespace for the generated code
-depend generate file dependencies
-D
由ide自动编译, 或是手动, tsc 命令来编译ts到js.
在src/test.ts
写入如下测试代码
import { ANTLRInputStream, CommonTokenStream } from 'antlr4ts';
import {HelloLexer} from "./antlr/HelloLexer";
import {HelloParser} from "./antlr/HelloParser";
// Create the lexer and parser
let inputStream = new ANTLRInputStream("hello hero");
let lexer = new HelloLexer(inputStream);
let tokenStream = new CommonTokenStream(lexer);
let parser = new HelloParser(tokenStream);
// Parse the input, where `compilationUnit` is whatever entry point you defined
let result = parser.r();
console.log(result);
好了dist目录里应该有我们所有的代码了. 在node_modules里应该存在依赖antlr4ts
./dist
├── antlr
│ ├── HelloLexer.d.ts
│ ├── HelloLexer.js
│ ├── HelloLexer.js.map
│ ├── HelloListener.d.ts
│ ├── HelloListener.js
│ ├── HelloListener.js.map
│ ├── HelloParser.d.ts
│ ├── HelloParser.js
│ └── HelloParser.js.map
├── test.d.ts
├── test.js
└── test.js.map
好了控制台应该能打印出R
规格的上下文对像了
RContext {
_parent: undefined,
invokingState: -1,
_start:
CommonToken {
_line: 1,
_charPositionInLine: 0,
_channel: 0,
index: 0,
_text: undefined,
_type: 1,
source: { source: [Object], stream: [Object] },
start: 0,
stop: 4 },
children:
[ TerminalNode { _symbol: [Object], _parent: [Circular] },
TerminalNode { _symbol: [Object], _parent: [Circular] } ],
_stop:
CommonToken {
_line: 1,
_charPositionInLine: 6,
_channel: 0,
index: 1,
_text: undefined,
_type: 2,
source: { source: [Object], stream: [Object] },
start: 6,
stop: 9 } }
你可能会很困惑这些内容, 具体请参阅或学习一下antlr基础知识, 以及typescript知识
下一篇文章将开始尝试写一个简单的parser