BASIC solutions: statements

Spread the love

My last post showcased what I thought was a complete GW-BASIC expression parsing solution. Hence, I pushed forward with a new project to implement statement parsing.

This went fine for a bit, but I quickly encountered overly complicated situations. Without access to the Sprache parser implementations, I was left parsing string values to extract expressions used within statements. This was less than ideal, so I pivoted and merged the separate projects back into a single one. Almost immediately the job became much simpler.

Commit after commit, I kept implementing support for more and more statements. It was almost too easy! (In general though expression parsing really is the hardest part of a compiler front end.)

Of course, these adventures never proceed without at least one critical issue. Just when I thought I was done, I pointed my glorious new line/statement parser at adventure.bas. It blew up on an input that I thought I had handled but slipped through the cracks, an expression like (X AND Y)=Z. I put in a quick fix but it was not sufficient to handle the general situation. Basically, due to the way that I implemented AND/OR expressions — having them in the upper level with separate forks for string and numeric expressions — I kept running into examples beyond the reach of my parser. Seeing that I was on the verge of a major refactor, I added several new tests. Then I set out to eliminate the string/number parser dichotomy and instead lean on semantic analysis to ensure valid results.

I started small by just adding the type information. With the groundwork laid, I could then add operator type checking. From there, it wasn’t a big leap to finalize the simplified grammar with proper type checking.

With the path now fully unblocked, I could complete the final set of statements needed to parse adventure.bas! A finishing touch to add the visitor pattern, similar to what I had done for expressions, and it was complete.

The code can now produce a valid AST of a sort for some subset of GW-BASIC programs.

Here is an example program, followed by a textual output of how my GWParse library interprets it:

10 CLS
20 INPUT "WHAT IS YOUR NAME";A$
30 IF A$="" THEN PRINT "TRY AGAIN." : GOTO 20
40 PRINT "HELLO, ";A$;"!"

Line(10, Cls())
Line(20, Input("WHAT IS YOUR NAME", StrV(A)))
Line(30, If(Eq(StrV(A), StrL("")), Print(StrL("TRY AGAIN."))), Goto(20))
Line(40, Print(StrL("HELLO, "), StrV(A), StrL("!")))

Next time, we will see if I can finally complete the trifecta — C# code generation.

Leave a Reply

Your email address will not be published. Required fields are marked *