diff --git a/package-lock.json b/package-lock.json index 80ce62a..14b4986 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,6 +20,7 @@ "digitaljs_lua": "github:yuyichao/digitaljs_lua#dev", "hammerjs": "^2.0.8", "lodash": "^4.17.21", + "luaparse": "^0.3.1", "path-browserify": "^1.0.1", "resize-observer-polyfill": "^1.5.1", "split-grid": "^1.0.11", @@ -4633,6 +4634,14 @@ "node": ">=10" } }, + "node_modules/luaparse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/luaparse/-/luaparse-0.3.1.tgz", + "integrity": "sha512-b21h2bFEbtGXmVqguHogbyrMAA0wOHyp9u/rx+w6Yc9pW1t9YjhGUsp87lYcp7pFRqSWN/PhFkrdIqKEUzRjjQ==", + "bin": { + "luaparse": "bin/luaparse" + } + }, "node_modules/make-dir": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", @@ -12680,6 +12689,11 @@ "yallist": "^4.0.0" } }, + "luaparse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/luaparse/-/luaparse-0.3.1.tgz", + "integrity": "sha512-b21h2bFEbtGXmVqguHogbyrMAA0wOHyp9u/rx+w6Yc9pW1t9YjhGUsp87lYcp7pFRqSWN/PhFkrdIqKEUzRjjQ==" + }, "make-dir": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", diff --git a/package.json b/package.json index b4a2b71..9c350fd 100644 --- a/package.json +++ b/package.json @@ -317,6 +317,7 @@ "digitaljs_lua": "github:yuyichao/digitaljs_lua#dev", "hammerjs": "^2.0.8", "lodash": "^4.17.21", + "luaparse": "^0.3.1", "path-browserify": "^1.0.1", "resize-observer-polyfill": "^1.5.1", "split-grid": "^1.0.11", diff --git a/src/lua_terminal.mjs b/src/lua_terminal.mjs index ff88273..d1f70ab 100644 --- a/src/lua_terminal.mjs +++ b/src/lua_terminal.mjs @@ -3,6 +3,41 @@ 'use strict'; import REPL from './repl.mjs'; +import * as luaparse from 'luaparse'; + +const unexpected_eof_suffix = (() => { + // This is basically how lua.c detect parser error... + // It would be nice if luaparse could give us a simpler ID to match... + // It's good enough for now and I don't really want to monkey patch luaparse ATM. + const err = luaparse.errors.unexpectedEOF; + return err.substring(err.length - 7); +})(); + +class ParseResult { + static OK = 1 + static EOF = 2 + static ERROR = 3 +} + +function try_parse(str) { + try { + luaparse.parse(str); + } + catch (e) { + if (e.message && e.message.endsWith(unexpected_eof_suffix)) + return ParseResult.EOF; + return ParseResult.ERROR; + } + return ParseResult.OK; +} + +function try_parse_with_return(str) { + // Do not append `;` here since we want the string to be at the end of the input. + const res = try_parse(`return ${str}`); + if (res === ParseResult.OK) + return res; + return Math.min(res, try_parse(str)); +} export class LuaTerminal extends REPL { #view @@ -28,8 +63,8 @@ export class LuaTerminal extends REPL { } #try_submit(data) { - // TODO: - // * automatically detect if we should take more input lines + if (try_parse_with_return(data) === ParseResult.EOF) + return false; this.#view.post({ command: 'runlua', name: `REPL[${this.#id++}]`,