print 1 + 2 + 3
来说,它会先执行 1 + 2 + 3
然后打印执行的结果。TokenType.PRINT
,在 Lexer::next
中增加对该关键字的预测分支,以及解析该关键字的 Lexer::readPrint
方法。NodeType.PRINT_STMT
已经它的定义 PrintStmt
。在 Parser::parseProg
中,我们增加了预测 print
语句的分支,Parser::parsePrintStmt
负责解析 print
语句。visitPrintStmt
方法,留给子类去实现。在 visitStmt
中,增加了对 NodeType.PRINT_STMT
类型的识别和处理。visitNumLiteral
中,我们将字符串通过 parseInt
转换成了整型,注意我们在定义数字的语法规则时,具有可选的前导零,当时做这样的选择,也是顺带利用了 JS 中 parseInt
方法的功能。visitBinaryExpr
中,我们对于两个操作数,我们分别调用 visitExpr
来取它们的值,然后根据不同的操作符执行了相应的运算,并返回运行结果,这样使得操作数取值的 visitExpr
调用总是可以拿到值:来自 parseInt 或者子节点的运算结果。visitPrintStmt
的操作就是打印运算的结果,对于求值则是委托给了 visitExpr
来完成。print 1 + 2 ** 3 * 5
:41
。因为我们的 hi 语言使用了和 JS 相同的运算符优先级和结合性,所以大家也可以将表达式 1 + 2 ** 3 * 5
直接粘贴到浏览器的控制台,来验证执行的结果是否和 hi 语言相同。