猿问

如何检测来源/调试Lexer的空值

我已经实现了ANTLR4的基本语法,以使用简单Javascript风格的语言构建JavaScript解释器。


当我运行脚本以转换代码(解析/生成/转译)时,我得到 TypeError: ctx.INT is not a function了来自转译器文件的代码。


这是我要编译的脚本

var fs = require('fs');

var antlr4 = require('antlr4');

var buildAst = require('./build-ast');

var mylangTranspiler = require('./mylang-transpiler');



function runScript(inputText) {

    var ast = buildAst(inputText);

    var transpiler = new mylangTranspiler();

    antlr4.tree.ParseTreeWalker.DEFAULT.walk(transpiler, ast);

    // eval(transpiler.output);


    fs.writeFile("./main.js", transpiler.output, function(err) {

        if(err) {

            return console.log(err);

        }


        console.log("The file was saved!");

    });

}


var contents = fs.readFileSync('./tests/test.mylang', 'utf8');

console.log(contents);


runScript(contents);


module.exports = runScript;

这是捕获错误的地方

mylangTranspiler.prototype.resolveExpr = function(ctx) {

    console.log(ctx);

    if (ctx.INT() != null) {

        return ctx.INT().getText();

    } else if (ctx.ID() != null) {

        return ctx.ID().getText();

    } else if (ctx.STRING() != null) {


        return ctx.STRING().getText().replace(/\$\{([^\}]+)\}/g, '" + $1 + "');

    } else return "undefined";

}

这是我的语法文件

grammar mylang;


compilationUnit: stmt*;


stmt

    : assignStmt

    | invocationStmt

    ;


assignStmt: SET ID TO expr;

invocationStmt: ID ((expr COMMA)* expr)?;


expr: expr (MUL | DIV) expr  # MulDiv

    | expr (ADD | SUB) expr  # AddSub

    | LPAREN expr RPAREN     # Parens

    | ID                     # ID

    | INT                    # Int

    | STRING                 # String

    ;


INT: [0-9]+;

STRING : '"' .*? '"' ;

ID: [a-zA-Z_] [a-zA-Z0-9_]*;


COMMA: ',';

SAY: 'show';

SET: 'set';

TO: 'to';


MUL: 'times';

DIV: 'by';

ADD: 'add';

SUB: 'sub';

LPAREN: '(';

RPAREN: ')';


WS : [ \t\r\n]+ -> skip;



我试图实现的是基本的计算器操作,变量分配和向控制台的打印,但是具有不同的语法,这些语法将转换为JavaScript。


HUX布斯
浏览 108回答 1
1回答

GCT1015

当您定义带有标记替代项的解析器规则时,每个替代项将获得自己的子类,并且只有该子类才会具有与该替代项的子规则相对应的getter方法。因此,鉴于您的语法,您具有以下子类ExprContext:MulDivContextAddSubContextParensContextIDContextIntContextStringContext其中只有IntContext一种INT()方法。因此INT(),ExprContext除非您首先确保它实际上是一个,否则不应调用an IntContext。ANTLR生成的侦听器和访问者将为每个标记的替代品使用enter和exit或visit方法,因此确保与aIntContext进行处理的方法是定义visitIntContext(ctx),visitStringContext(ctx)而不是诸如此类visitExprContext(ctx),然后您将知道ctx只能曾经拥有与该替代方案相对应的类型。
随时随地看视频慕课网APP

相关分类

JavaScript
我要回答