Hey,
Loved the article but I when going through saw a few things that are inaccurate to the Lua grammar. I understand the intent is to teach a subset of Lua, not a production ready environment. Not to be pedantic about it, but this is more of a dialect of Lua than a subset.
In the article you state:
The boring part is defining the tree. Generally speaking (and specifically for this project), the syntax tree is a list of statements. Statements can be function definitions or expression statements or if statements or return statements or local declarations.
While this is true for most languages, it's actually incorrect for Lua. Lua's grammar uniquely disallows expressions as statements with one exception, function calls.
This is important in resolving ambiguity that looks like this:
local x = 1 -- Does the statement end here?
- 1 -- Or does it end here?
The next difference is:
Return statements just check for the return keyword, an expression, and a semicolon.
Lua optionally allows semicolon statement terminators. They are not required. This introduces ambiguity in situations like this:
function foo()
return
bar()
end
Parsing this can either mean "return nothing and call bar" or "return the result of call to bar"
Lua's rules solves this ambiguity by forcing return to always be the last statement in the block.
Lua is a rather unique whitespace agnostic language. These 2 rules are pivotal to that, so I was hoping to see how you implemented Lua's grammar. Again none of this is to criticize your article or implementation, I quite enjoyed it as a fan of rust, Lua and language design at large.