Created
March 27, 2021 23:28
-
-
Save x4fx77x4f/55ce1af230e306f2c5868a908236f3ec to your computer and use it in GitHub Desktop.
Very basic BASIC lexer in Lua
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--@name BASIC | |
--@server | |
local code = [[ | |
10 PRINT "Hello, World!" | |
20 END | |
]] | |
local lexer = {} | |
lexer.data = code | |
lexer.index = 1 | |
lexer.len = #code | |
lexer.out = {} | |
function lexer:eof() | |
return self.index > self.len | |
end | |
function lexer:nextChars(n) | |
local index = self.index | |
return string.sub(self.data, index, index+(n and n-1 or 0)) | |
end | |
function lexer:consumeChars(n) | |
n = n or 1 | |
local chars = self:nextChars(n) | |
self.index = self.index+n | |
return chars | |
end | |
function lexer:consumeWhile(cond) | |
local out = {} | |
local i = 1 | |
while true do | |
local char = self:nextChars(1) | |
if cond(char) then | |
self.index = self.index+1 | |
out[i] = char | |
i = i+1 | |
else | |
break | |
end | |
end | |
return table.concat(out) | |
end | |
function lexer.isNumber(str) | |
return string.find(str, '%d') | |
end | |
function lexer.isWhitespace(str) | |
return string.find(str, '%s') | |
end | |
function lexer.isAlphabetic(str) | |
return string.find(str, '%a') | |
end | |
function lexer.isNotQuote(str) | |
return str ~= '"' | |
end | |
function lexer:consumeString() | |
assert(not self.isNotQuote(self:consumeChars()), "missing beginning quote") | |
local str = self:consumeWhile(self.isNotQuote) | |
self.index = self.index+1 | |
return str | |
end | |
function lexer:consumeLine() | |
if self:nextChars() == '\n' then | |
self.index = self.index+1 | |
return | |
end | |
local lineno = self:consumeWhile(self.isNumber) | |
self:consumeWhile(self.isWhitespace) | |
local keyword = self:consumeWhile(self.isAlphabetic) | |
self:consumeWhile(self.isWhitespace) | |
local arguments = {} | |
if keyword == 'PRINT' then | |
arguments[1] = self:consumeString() | |
end | |
self.out[lineno] = { | |
keyword = keyword, | |
arguments = arguments | |
} | |
assert(self:consumeChars() == '\n' or self:eof(), "too many parameters") | |
end | |
function lexer:consumeLines() | |
while not self:eof() do | |
self:consumeLine() | |
end | |
end | |
lexer:consumeLines() | |
do return printTable(lexer.out) end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment