Prog Blog for March 7th, 2026

In Febrary, and today, I completed the next three chapters of Crafting Interpreters, "Evaluating Expressions", "Statements and State", and "Control Flow".

I now have a language that can branch with if statements, do basic math, and perform loops. There are four chapters remaining; "Functions", "Resolving and Binding", "Classes", and "Inheritance". I will definitely need functions and maybe some of resolving and binding, but because this language does not have classes, I'll read the last two chapters for informational purposes only.

At this point, the language used as an example in the book, Lox, and my language, TaylorBasic, have diverged quite a bit. Mostly this started around the control flow section, because TaylorBasic uses If-Then-Else-End, whereas Lox uses the traditional C-like if statement structure.

I also needed to create some lookahead functionality in the parser that Lox doesn't need. This mostly stems from two language characteristics of TaylorBasic:

  • Statements start with ":" instead of ending with ";". This means, sometimes, the parser needs to look ahead two tokens to make a decision. An example of this is when collecting statements for an Else block, the parser stops when it sees End. Unfortunately, that pesky ":" token is in front of End, so we have to peek past the peek.
  • Setting variables is of the form EXPRESSION -> IDENTIFIER, instead of the usual IDENTIFIER = EXPRESSION ; In the book, they use the pattern of a "var" statment followed by an identifier and equals sign as indicating a variable declaration. I have to scan the entire statement for "->" in order to tell. One thing I puzzled over a lot is if I could just add "->" to expression parsing, and parse it like a normal binary operator expression, but I was unable to use STO where you would use expressions, in the TI-Basic emulator. So, doing something like Disp (3->A) produces a syntax error.
I think there's probably ways around both of these issues; for the first item, possibly something like an implied first ":" and then expect ":" after statements (or, in other words) before the next statement, might work. But for now I'm going to leave it as is.

Another divergence is that I don't think TI-Basic has logical operator short circuiting. So, where the book adds it as another expression type, I just lumped mine into my existing binary expressions. I had to add truthiness here also, as before I got away with it because there is no unary - in TI-Basic.

Next session, I'm going to add some other things that TI-Basic has that are considered control flow or other statements: releate loops, IS/DS, Stop, and Delvar. I don't know how to do Goto (the main control flow tool in TI-Basic) but I think I might learn in the upcoming chapters. I'll leave it here with some nasty code to parse if statements:


      def if_statement(self):
        condition = self.expression()
        then_branch = []
        else_branch = []
        self._consume(TokenType.COLON, "Expected ':' before THEN statement.")
        if self._match([TokenType.THEN]):
            collect_mode = "then"
            while True:
                if self._skip_peek().token_type == TokenType.END:
                    self._advance()
                    self._advance()
                    if collect_mode == "then":
                        elseBranch = []
                    break
                elif self._skip_peek().token_type == TokenType.ELSE:
                    self._advance()
                    self._advance()
                    collect_mode = "else"
                    continue
                else:
                    new_stmt = self.declaration()
                    if collect_mode == "then":
                        then_branch.append(new_stmt)
                    else:
                        else_branch.append(new_stmt)
        else:
            thenBranch.append(self.declaration())

        rv = StmtIf(condition, then_branch, else_branch)
        return rv