【问题标题】:For loops with antlr 4使用 antlr 4 的循环
【发布时间】:2021-04-06 09:58:22
【问题描述】:

我正在从事一个 UNI 项目,我们必须从头开始开发一种编程语言。我们使用 antlr4 来生成解析树。我目前正在努力让 for 循环工作,我有语法并且可以取出值。我目前的问题是如何在 for 循环体中循环语句。

这是我的语法:

grammar LCT;
program: stmt*;
stmt: assignStmt
    | invocationStmt
    | show
    | forStatement
;

assignStmt: VAR ID '=' expr;

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

expr: ID | INT | STRING;

show: 'show' (INT | STRING | ID);

block : '{' statement* '}' ;

statement : block
           | show
           | assignStmt
;

forStatement : 'loop' ('(')? forConditions (')')? statement* ;
forConditions : iterator=expr  'from' startExpr=INT range='to' endExpr=INT ;


//tokens
COMMA: ',';
VAR: 'var';
INT: [0-9]+;
STRING: '"' (~('\n' | '"'))* '"';
ID: [a-zA-Z_] [a-zA-Z0-9_]*;

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

这是当前支持分配和打印整数的监听器

package LCTlang;

import java.util.HashMap;

public class LCTCustomBaseListener extends LCTBaseListener {

    HashMap<String, Integer> variableMap = new HashMap();
    String[] keyWords = {"show", "var"};



    @Override public void exitAssignStmt(LCTParser.AssignStmtContext ctx) {
        this.variableMap.put(ctx.ID().getText(),
                Integer.parseInt(ctx.expr().getText()));
    }


    @Override public void exitInvocationStmt(LCTParser.InvocationStmtContext ctx) {
        this.variableMap.put(ctx.name.getText(),
                Integer.parseInt(ctx.ID().getText()));
    }

    @Override
    public void exitShow(LCTParser.ShowContext ctx) {
        if(ctx.INT() != null) {
            System.out.println(ctx.INT().getText());
        }
        if(ctx.STRING() != null) {
            System.out.println(ctx.ID().getText());
        }
        else if(ctx.ID() != null) {
            System.out.println(this.variableMap.get(ctx.ID().getText()));
        }
    }

    @Override public void exitForStatement(LCTParser.ForStatementContext ctx) {
        int start = Integer.parseInt(ctx.forConditions().startExpr.getText());
        int end = Integer.parseInt(ctx.forConditions().endExpr.getText());
        String varName = ctx.forConditions().iterator.getText();
        int i;

        for (i = start; i < end; i++) {
            for (LCTParser.StatementContext state : ctx.statement()){
                System.out.println(state);
            }
        }
    }
}

我的问题在于语句的循环,以及如何完成。

【问题讨论】:

标签: java loops listener antlr4


【解决方案1】:

侦听器将是一个糟糕的执行选择。您已将树导航转换为 Tree Walker(仅点击每个节点一次),当它遇到您感兴趣的节点时会回叫您。您不会说服它遍历某个迭代节点的子节点( while、for 等)不止一次,这几乎就是迭代结构的重点。它不会检测到节点是对函数的调用,然后导航到该函数。它只是穿过 ParseTree。

对于一些相当简单的语法(通常类似于表达式求值器(可能是计算器),您可以设置一个访问者来返回您的表达式数据类型(可能是计算器的浮点数) .

在您的情况下,我建议 ANTLR 提供了它的价值。它是一个 Parser,并为您提供了 ParseTree。现在由您来编写代码,利用该解析树来执行功能。您现在正处于为您的语言创建运行时的世界中。感谢 ANTLR 使其易于解析,并提供了不错的错误消息和强大的错误恢复。

要执行您的逻辑,您需要编写使用这些数据结构的代码,跟上变量的当前值,并根据这些值决定执行包含在 for/while/.. 中的所有内容。 。 环形。您将有类似的运行时工作来评估布尔表达式以决定是否在 if/else 语句等中执行子级。此运行时还必须跟上调用其他函数的函数的调用堆栈等。简而言之,执行您的结果逻辑将涉及引用已解析的输入,但不会特别像导航您的解析树。

(注意:很多人发现完整的解析树导航起来有点乏味(它往往有很多中间节点)。过去,我编写了一个访问者来产生更像 AST 的东西(抽象语法树)。它是一个修剪过的树,具有我想要进一步处理的结构。这不是必需的,但您可能会发现它更容易使用。)

【讨论】:

    猜你喜欢
    • 2014-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-28
    • 1970-01-01
    • 2020-09-26
    • 1970-01-01
    相关资源
    最近更新 更多