diff --git a/.gitignore b/.gitignore
index 4560abe..31241da 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,5 +59,5 @@ typings/
# next.js build output
.next
-
+dist/
.cache
\ No newline at end of file
diff --git a/browser.js b/browser.js
new file mode 100644
index 0000000..383b442
--- /dev/null
+++ b/browser.js
@@ -0,0 +1,11 @@
+import { run, Environment } from './index'
+
+const button = document.getElementById('run')
+button.onclick = () => {
+ const code = document.getElementById('code').value
+ const browserEnv = new Environment()
+ browserEnv.setBuiltin('alert', (_, arg) => alert(arg[0]))
+ browserEnv.setBuiltin('confirm', (_, elem) => confirm(elem[0]))
+ browserEnv.setBuiltin('prompt', (_, p) => prompt(p[0], p.length > 1 ? p[1] : null))
+ run(code, browserEnv)
+}
diff --git a/cli.js b/cli.js
new file mode 100755
index 0000000..985b425
--- /dev/null
+++ b/cli.js
@@ -0,0 +1,78 @@
+#! /usr/bin/env node
+const fs = require('fs')
+const readline = require('readline')
+const Environment = require('./environment')
+const { run } = require('./index')
+
+let options = {
+ debug: false,
+ history: 30,
+ prompt: '>'
+}
+
+const runPrompt = () => {
+ const prompt = options.prompt + ' '
+ process.stdout.write(prompt)
+ const lineReader = readline.createInterface({
+ input: process.stdin,
+ output: process.stdout,
+ terminal: true,
+ prompt: prompt,
+ historySize: +options.history
+ })
+ const env = new Environment()
+ env.setBuiltin('readFile', (_vars, args) => fs.readFileSync(args[0], 'utf8'))
+
+ lineReader.on('line', line => {
+ let code = line
+ if (!line.endsWith(';') && !line.endsWith('}')) code += ';'
+ // TODO: Support multi-line block statements
+ const lastLine = run(code, env, options.debug)
+ console.log(JSON.stringify(lastLine))
+ process.stdout.write(prompt)
+ })
+}
+
+const runFile = filename => {
+ try {
+ const file = fs.readFileSync(filename, 'utf8')
+ run(file, undefined, options.debug)
+ } catch (e) {
+ console.error(`YALI could not read the file ${filename}`)
+ console.error(e)
+ }
+}
+
+const optionRegex = /--(\w+)(?:=(.+))?/
+const processOptions = args =>
+ args
+ .map(arg => {
+ const match = optionRegex.exec(arg)
+ if (match) {
+ const [_, option, value] = match
+ if (!value) {
+ options[option] = !options[option]
+ } else {
+ options[option] = value
+ }
+ } else {
+ return arg
+ }
+ })
+ .filter(Boolean)
+
+const main = argv => {
+ process.title = 'YALI'
+ const args = processOptions(argv.slice(2))
+ if (options.debug) console.log(options)
+ if (args.length > 1) {
+ console.error('Usage: jlox [script]')
+ return 64
+ } else if (args.length === 1) {
+ runFile(args[0])
+ } else {
+ runPrompt()
+ }
+}
+
+return main(process.argv)
diff --git a/index.html b/index.html
new file mode 100644
index 0000000..616e3d7
--- /dev/null
+++ b/index.html
@@ -0,0 +1,27 @@
+
+
+
+
+
+ YALI.js
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/index.js b/index.js
index 95786a5..39d9ca6 100755
--- a/index.js
+++ b/index.js
@@ -1,27 +1,18 @@
-#! /usr/bin/env node
-const fs = require('fs')
const chalk = require('chalk')
-const readline = require('readline')
const Tokenizer = require('./tokenizer')
const Parser = require('./parser')
const { LoxError } = require('./errors')
const Interpreter = require('./interpreter')
const Environment = require('./environment')
-let options = {
- debug: false,
- history: 30,
- prompt: '>'
-}
-
-const run = (code, environment) => {
+const run = (code, environment, debug = false) => {
try {
const tokenizer = new Tokenizer(code)
const tokens = tokenizer.scanTokens()
- if (options.debug) console.log(tokens)
+ if (debug) console.log(tokens)
const parser = new Parser(tokens)
const statements = parser.parse()
- if (options.debug) console.log(statements)
+ if (debug) console.log(statements)
const interpreter = new Interpreter(environment)
let lastStatement
for (let statement of statements) {
@@ -59,69 +50,7 @@ const run = (code, environment) => {
}
}
-const runPrompt = () => {
- const prompt = options.prompt + ' '
- process.stdout.write(prompt)
- const lineReader = readline.createInterface({
- input: process.stdin,
- output: process.stdout,
- terminal: true,
- prompt: prompt,
- historySize: +options.history
- })
- const env = new Environment()
- env.setBuiltin('readFile', (_vars, args) => fs.readFileSync(args[0], 'utf8'))
-
- lineReader.on('line', line => {
- let code = line
- if (!line.endsWith(';') && !line.endsWith('}')) code += ';'
- // TODO: Support multi-line block statements
- const lastLine = run(code, env)
- console.log(JSON.stringify(lastLine))
- process.stdout.write(prompt)
- })
-}
-
-const runFile = filename => {
- try {
- const file = fs.readFileSync(filename, 'utf8')
- run(file)
- } catch (e) {
- console.error(`YALI could not read the file ${filename}`)
- console.error(e)
- }
-}
-
-const optionRegex = /--(\w+)(?:=(.+))?/
-const processOptions = args =>
- args
- .map(arg => {
- const match = optionRegex.exec(arg)
- if (match) {
- const [_, option, value] = match
- if (!value) {
- options[option] = !options[option]
- } else {
- options[option] = value
- }
- } else {
- return arg
- }
- })
- .filter(Boolean)
-
-const main = argv => {
- process.title = 'YALI'
- const args = processOptions(argv.slice(2))
- if (options.debug) console.log(options)
- if (args.length > 1) {
- console.error('Usage: jlox [script]')
- return 64
- } else if (args.length === 1) {
- runFile(args[0])
- } else {
- runPrompt()
- }
-}
-
-return main(process.argv)
+module.exports = {
+ run,
+ Environment
+}
\ No newline at end of file
diff --git a/package.json b/package.json
index aa6da64..e06f657 100644
--- a/package.json
+++ b/package.json
@@ -1,9 +1,9 @@
{
"name": "yali",
- "version": "1.0.0",
+ "version": "0.10.2",
"description": "Yet Another Lox Interpreter. Javascript Implementation of the Lox Programming Language",
"main": "index.js",
- "bin": "./index.js",
+ "bin": "./cli.js",
"scripts": {
"test": "jest",
"format": "prettier --write **/*.js",