Skip to content

Instantly share code, notes, and snippets.

@bjconlan
Last active July 26, 2016 10:25
Show Gist options
  • Save bjconlan/acf8063e41d80ae76650e237a812ab22 to your computer and use it in GitHub Desktop.
Save bjconlan/acf8063e41d80ae76650e237a812ab22 to your computer and use it in GitHub Desktop.
Pico8 (Lua subset) hand rolled parser/lexer
function plexy(src) {
const TOKEN = {
STRING: 0,
NUMBER: 1,
LABEL: 2,
SYMBOL: 3,
'...': 4,
'..': 5,
'.': 6,
'==': 7,
'=': 8,
'~=': 9,
'<=': 10,
'<': 11,
'>=': 12,
'>': 13,
'-=': 14,
'-': 15,
'+=': 16,
'+': 17,
'/=': 18,
'/': 19,
'*': 20,
'*=': 21,
'%=': 22,
'%': 23,
'^=': 24,
'^': 25,
'#': 26,
':': 27,
';': 28,
',': 29,
'(': 30,
')': 31,
'{': 32,
'}': 33,
'[': 34,
']': 35,
'and': 36,
'continue': 37,
'do': 38,
'else': 39,
'elseif': 40,
'end': 41,
'false': 42,
'for': 43,
'function': 44,
'goto': 45,
'if': 46,
'in': 47,
'local': 48,
'nil': 49,
'not': 50,
'or': 51,
'repeat': 52,
'return': 53,
'then': 54,
'true': 55,
'until': 56,
'while': 57
};
var tokens = [];
function addToken(token, start, end = start + 1) {
return tokens.push({token: token, start: start, end: end});
}
function isDigit(c) { return c >= '0' && c <= '9'; }
function isAlpha(c) { return (c >= 'a' && c <= 'z') || c === '_'; }
for (var i = 0; i < src.length; i++) {
var c = src[i];
// whitespace (ignore)
if (c === ' ' || c === '\t' || c === '\r' || c === '\n') {
while (++i < src.length && (src[i] === ' ' || src[i] === '\t' ||
src[i] === '\r' || src[i] === '\n'));
c = src[i];
}
// comment
if (c === '-' && src[i+1] === '-') {
if (src[i+2] === '[' && src[i+3] === '[') {
i = src.indexOf(']]--', i + 4) + 3;
} else {
i = src.indexOf('\n', i + 2);
}
continue;
}
if (isDigit(c)) {
var s = i;
while (++i < src.length && isDigit(src[i]));
addToken(TOKEN.NUMBER, s, i);
--i;
continue;
}
if (isAlpha(c)) {
var s = i;
while (++i < src.length && (isAlpha(src[i]) || isDigit(src[i])));
addToken(TOKEN[src.substring(s, i)] || TOKEN.SYMBOL, s, i);
--i;
continue;
}
switch (c) {
case '"': case "'":
var s = i + 1;
do { i = src.indexOf(c, i + 1); } while (i < src.length && src[i-1] === '\\');
addToken(TOKEN.STRING, s, i - 1);
break;
case '.':
src[i+1] === '.'
? src[i+2] === '.'
? addToken(TOKEN['...'], i, i += 2)
: addToken(TOKEN['..'], i, ++i)
: addToken(TOKEN['.'], i);
break;
case ':':
if (src[i+1] === ':') {
s = i + 2;
i = src.indexOf('::', s) + 1;
addToken(TOKEN.LABEL, s, i - 2);
break;
}
case '=': case '-': case '+': case '*': case '/':
case '<': case '>': case '%': case '^':
if (src[i+1] === '=') {
addToken(TOKEN[c+'='], i, ++i);
break;
}
case '#': case ';': case ',': case '(': case ')':
case '{': case '}': case '[': case ']':
addToken(TOKEN[c], i);
break;
case '~': // let it just flow though we ignore ~ by itself.
if (src[i+1] === '=') {
addToken(TOKEN['~='], i, ++i);
}
default:
console.log('>>', c, i, '<<');
}
}
return tokens;
}
/*
var src = `
-- hello world
-- by zep
t = 0
function _update()
t += 1
end
function _draw()
cls()
for i=1,11 do
for j0=0,7 do
j = 7-j0
col = 7+j
t1 = t + i*4 - j*2
x = cos(t0)*5
y = 38 + j + cos(t1/50)*5
pal(7,col)
spr(16+i, 8+i*8 + x, y)
end
end
print("this is pico-8",
37, 70, 14) --8+(t/4)%8)
print("nice to meet you",
34, 80, 12) --8+(t/4)%8)
end`;
plexy(src).map((t) => src.substring(t.start, t.end));*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment