使用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 (四)
  • 使用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命令基本一致具体可通过 antlr4tsantlr4查看

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

你可能感兴趣的:(使用antlr4, 用ts/js还原protobuf生成的java代码为pb (一))