antlr 生成 java 代码_使用antlr4, 用ts/js还原protobuf生成的java代码为pb (二)

目录:

现在开始写一个简单公式计算器的parser.

expr.g4

grammar Expr ;

prog: stat+ ;

stat: expr NEWLINE # printExpr

| ID '=' expr NEWLINE # assign

| NEWLINE # empty

;

expr: expr op=(MUL|DIV) expr # MulDiv

| expr op=(ADD|SUB) expr # AddSub

| INT # int

| ID # id

| '(' expr ')' # parentheses

;

MUL : '*' ; // assigns token name to '*' used above in grammar '/' ;

DIV : '/' ;

ADD : '+' ;

SUB : '-' ;

ID : [a-zA-Z]+ ;

INT : [0-9]+ ;

NEWLINE : '\r'? '\n' ;

WS: [ \t]+ -> skip ;

#号后面的标签必不可少, 这是用来方便visitor来处理的, 具体可以参阅calculator-visitor

这里我们使用常见的visitor模式来处理(另一种是用listener), 使用命令如下

antlr4ts -visitor ./src/antlr/Expr.g4

CustomVisitor代码如下

import {ExprVisitor} from "./antlr/ExprVisitor";

import {

AddSubContext,

AssignContext,

ExprParser,

IdContext,

IntContext,

MulDivContext,

ParenthesesContext,

PrintExprContext

} from "./antlr/ExprParser";

import {AbstractParseTreeVisitor} from "antlr4ts/tree";

export class CustomVisitor extends AbstractParseTreeVisitor implements ExprVisitor {

/** "memory" for our calculator; variable/value pairs go here */

memory: Map = new Map();

/** ID '=' expr */

public visitAssign(ctx: AssignContext): number {

let id = ctx.ID().text; // id is left-hand side of '='

let value = this.visit(ctx.expr()); // compute value of expression on right

this.memory.set(id, value); // store it in our memory

return value;

}

/** expr */

public visitPrintExpr(ctx: PrintExprContext) {

return this.visit(ctx.expr()); // evaluate the expr child

}

/** INT */

public visitInt(ctx: IntContext) {

return parseInt(ctx.INT().text);

}

/** ID */

public visitId(ctx: IdContext) {

let id = ctx.ID().text;

if (this.memory.has(id)) {

let value = this.memory.get(id);

console.log(`this is a assign expr, the [${id}] value is [${value}]`)

return value;

}

return 0;

}

/** expr op=('*'|'/') expr */

public visitMulDiv(ctx: MulDivContext) {

let left = this.visit(ctx.expr(0)); // get value of left subexpression

let right = this.visit(ctx.expr(1)); // get value of right subexpression

if (ctx._op.type == ExprParser.MUL) return left * right;

return left / right; // must be DIV

}

/** expr op=('+'|'-') expr */

public visitAddSub(ctx: AddSubContext) {

let left = this.visit(ctx.expr(0)); // get value of left subexpression

let right = this.visit(ctx.expr(1)); // get value of right subexpression

if (ctx._op.type == ExprParser.ADD) return left + right;

return left - right; // must be SUB

}

/** '(' expr ')' */

public visitParentheses(ctx: ParenthesesContext) {

return this.visit(ctx.expr()); // return child expr's value

}

protected defaultResult(): number {

return undefined;

}

}

测试代码如下

import {ANTLRInputStream, CommonTokenStream} from "antlr4ts";

import {ExprLexer} from "./antlr/ExprLexer";

import {ExprParser, ProgContext} from "./antlr/ExprParser";

import {CustomVisitor} from "./CustomVisitor";

// Create the lexer and parser

let inputStream = new ANTLRInputStream("1+2+3\n");

let lexer = new ExprLexer(inputStream);

let tokenStream = new CommonTokenStream(lexer);

let parser = new ExprParser(tokenStream);

// Parse the input, where `compilationUnit` is whatever entry point you defined

let result: ProgContext = parser.prog();

// console.log(result);

let value = (new CustomVisitor()).visit(result);

console.log(value);

由于代码中可能包含赋值表达式, 所以对于赋值表达式在代码里作了打印操作.

现改变let inputStream = new ANTLRInputStream("1+2+3\n");中的1+2+3\n 为其他计算表达式试试看结果对不对

下一章将开始解释java代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值