尝试理解解析器

发布于 2024-10-30 14:04:45 字数 187 浏览 1 评论 0原文

我正在尝试使用 JavaCC 构建一个简单的命令行计算器,可以处理各种表达式。虽然有很多关于如何编写语法的教程,但到目前为止我所看到的都没有解释随后发生的事情。

我现在的理解是,将字符串传递到解析器后,它会被分割成标记并变成解析树。接下来会发生什么?我是否遍历解析树,对每个节点的内容进行一系列 if-else 字符串比较,然后执行适当的函数?

I'm trying to use JavaCC to build a simple command line calculator that can handle a variety of expressions. While there are plenty of tutorials out there on how to write grammars, none that I've seen so far explain what happens afterwards.

What I understand right now is that after a string is passed into the parser, it's split into a tokens and turned into a parse tree. What happens next? Do I traverse through the parse tree doing a bunch of if-else string comparisons on the contents of each node and then perform the appropriate function?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

野味少女 2024-11-06 14:04:45

我强烈建议您观看 Scott Stanchfield 的 ANTLR 3.x 教程。即使您最终没有使用 ANTLR(这对您的项目来说可能有点大材小用,但我对此表示怀疑),通过观察他的思考过程,您也会学到很多东西。

一般来说,这个过程是......

  1. 构建一个词法分析器来理解您的标记
  2. 构建一个解析器,可以验证和理解输入并将输入组织到抽象语法树(AST)中,该抽象语法树应该表示简化/易于使用的版本您的语法
  3. 基于 AST 运行任何计算

I highly suggest you watch Scott Stanchfield's ANTLR 3.x tutorials. Even if you don't end up using ANTLR, which may be overkill for your project but I doubt it, you will learn a lot by watching him go through the thought process.

In general the process is...

  1. Build a lexer to understand your tokens
  2. Build a parser that can validate and understand and organize the input into an abstract syntax tree (AST) which should represent a simplified/easy-to-work-with version of your syntax
  3. Run any calculation based on the AST
林空鹿饮溪 2024-11-06 14:04:45

您需要根据需要实际编译或解释它。

对于计算器,您只需要递归访问树并评估解析的树,而使用更复杂的语言,您必须将其翻译为汇编语言-类似,但保留了底层架构的抽象。

当然,您可以开发自己的简单虚拟机,该虚拟机能够执行一组在您的语言中进行编译的指令,但在您的情况下这会有点过分……只需访问解析树即可。就像这样:

enum Operation {
  PLUS, MINUS
}

interface TreeNode {
  float eval();
}

class TreeFloat implements TreeNode {
  float val;
  float eval() { return val; }
}

class TreeBinaryOp implements TreeNode {
  TreeNode first;
  TreeNode second;
  Operation op;

  float eval() {
    if (op == PLUS)
      return first.eval()+second.eval();
}

然后你只需在树的根上调用 eval 函数即可。可能需要进行语义检查(如果您计划使用变量或其他内容,则还需要构建符号表)。

You need to actually compile or interpret it according to what you need..

For a calculator you just need to visit the tree recursively and evaluate the parsed tree while with a more complex language you would have to translate it to an intermediate language which is assembly-like but keeps abstraction from the underlying architecture.

Of course you could develop your own simple VM that is able to execute a set of instruction in which your language compiles but it would be overkill in your case.. just visit the parse tree. Something like:

enum Operation {
  PLUS, MINUS
}

interface TreeNode {
  float eval();
}

class TreeFloat implements TreeNode {
  float val;
  float eval() { return val; }
}

class TreeBinaryOp implements TreeNode {
  TreeNode first;
  TreeNode second;
  Operation op;

  float eval() {
    if (op == PLUS)
      return first.eval()+second.eval();
}

Then you just call the eval function on the root of the tree. A semantic checking could be needed (with the construction of a symbol table too if you plan to have variables or whatever).

云裳 2024-11-06 14:04:45

我是否遍历解析树,对每个节点的内容进行一系列 if-else 字符串比较,然后执行适当的函数?

不,不需要构建解析树来实现计算器。在创建新节点对象的代码部分中,只需进行计算并返回一个数字即可。

JavaCC 允许您为产生式选择任何返回类型,因此只需提供您的返回号即可。

Do I traverse through the parse tree doing a bunch of if-else string comparisons on the contents of each node and then perform the appropriate function?

No, there's no need to build a parse tree to implement a calculator. In the parts of the code where you would create a new node object, just do the calculations and return a number.

JavaCC allows you to choose any return type for a production, so just have your's return numbers.

〃温暖了心ぐ 2024-11-06 14:04:45

某些解析器生成器(例如 YACC)允许您将操作放入语法中,因此当您应用某个产生式时,您还可以在该产生式期间应用定义的操作。

例如,在 YACC 中:

E: NUM + NUM     {$ = $1.value + $2.value};

会将 NUM 的值相加并将结果返回到 E 非终结符。

不确定 JavaCC 可以让您做什么。

Some parser generators (such as YACC) let you put actions within the grammar so when you apply a certain production you can also apply a defined action during that production.

E.g. in YACC:

E: NUM + NUM     {$ = $1.value + $2.value};

would add the values of NUM and return the result to the E non-terminal.

Not sure what JavaCC lets you do.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文