pull/60/merge
Javier Chávarri 7 years ago committed by GitHub
commit 5b03ddf249

5
.gitignore vendored

@ -0,0 +1,5 @@
.DS_Store
.merlin
npm-debug.log
/lib/bs/
/node_modules/

@ -0,0 +1,14 @@
// This is the configuration file used by BuckleScript's build system bsb. Its documentation lives here: http://bucklescript.github.io/bucklescript/docson/#build-schema.json
// BuckleScript comes with its own parser for bsconfig.json, which is normal JSON, with the extra support of comments and trailing commas.
{
"name": "the-super-tiny-compiler",
"version": "0.1.0",
"bsc-flags": ["-bs-super-errors"],
"sources": [
"src"
],
"bs-dependencies" : [
// add your dependencies here. You'd usually install them normally through `npm install my-dependency`. If my-dependency has a bsconfig.json too, then everything will work seamlessly.
],
"namespace": true
}

@ -0,0 +1,305 @@
// Generated by BUCKLESCRIPT VERSION 1.9.3, PLEASE EDIT WITH CARE
'use strict';
var List = require("bs-platform/lib/js/list.js");
var Block = require("bs-platform/lib/js/block.js");
var $$String = require("bs-platform/lib/js/string.js");
var Caml_string = require("bs-platform/lib/js/caml_string.js");
function explode(s) {
var _i = s.length - 1 | 0;
var _l = /* [] */0;
while(true) {
var l = _l;
var i = _i;
if (i < 0) {
return l;
} else {
_l = /* :: */[
Caml_string.get(s, i),
l
];
_i = i - 1 | 0;
continue ;
}
};
}
function tokenizer(input) {
var _input = explode(input);
var _current = /* None */0;
var _tokens = /* [] */0;
while(true) {
var tokens = _tokens;
var current = _current;
var input$1 = _input;
if (input$1) {
var head = List.hd(input$1);
var tail = List.tl(input$1);
var exit = 0;
var exit$1 = 0;
var exit$2 = 0;
var switcher = head - 32 | 0;
if (switcher > 9 || switcher < 0) {
exit$2 = 3;
} else {
switch (switcher) {
case 0 :
if (current) {
var match = current[0];
if (typeof match === "number") {
exit$1 = 2;
} else {
switch (match.tag | 0) {
case 0 :
_tokens = /* :: */[
/* Number */Block.__(0, [match[0]]),
tokens
];
_current = /* None */0;
_input = tail;
continue ;
case 1 :
exit$2 = 3;
break;
case 2 :
_tokens = /* :: */[
/* Name */Block.__(2, [match[0]]),
tokens
];
_current = /* None */0;
_input = tail;
continue ;
}
}
} else {
exit$1 = 2;
}
break;
case 2 :
if (current) {
var match$1 = current[0];
if (typeof match$1 === "number") {
return List.rev(tokens);
} else if (match$1.tag === 1) {
_tokens = /* :: */[
/* String */Block.__(1, [match$1[0]]),
tokens
];
_current = /* None */0;
_input = tail;
continue ;
} else {
return List.rev(tokens);
}
} else {
_current = /* Some */[/* String */Block.__(1, [""])];
_input = tail;
continue ;
}
break;
case 1 :
case 3 :
case 4 :
case 5 :
case 6 :
case 7 :
exit$2 = 3;
break;
case 8 :
if (current) {
exit$2 = 3;
} else {
_tokens = /* :: */[
/* OpenParen */0,
tokens
];
_current = /* None */0;
_input = tail;
continue ;
}
break;
case 9 :
if (current) {
var match$2 = current[0];
if (typeof match$2 === "number") {
return List.rev(tokens);
} else {
switch (match$2.tag | 0) {
case 0 :
_tokens = /* :: */[
/* CloseParen */1,
/* :: */[
/* Number */Block.__(0, [match$2[0]]),
tokens
]
];
_current = /* None */0;
_input = tail;
continue ;
case 1 :
exit$2 = 3;
break;
case 2 :
_tokens = /* :: */[
/* CloseParen */1,
/* :: */[
/* Name */Block.__(2, [match$2[0]]),
tokens
]
];
_current = /* None */0;
_input = tail;
continue ;
}
}
} else {
_tokens = /* :: */[
/* CloseParen */1,
tokens
];
_current = /* None */0;
_input = tail;
continue ;
}
break;
}
}
if (exit$2 === 3) {
if (current) {
var match$3 = current[0];
if (typeof match$3 === "number") {
exit$1 = 2;
} else if (match$3.tag === 1) {
_current = /* Some */[/* String */Block.__(1, [match$3[0] + $$String.make(1, head)])];
_input = tail;
continue ;
} else {
exit$1 = 2;
}
} else {
exit$1 = 2;
}
}
if (exit$1 === 2) {
if (head >= 32) {
if (head < 58) {
if (head >= 33) {
if (head >= 48) {
if (current) {
var match$4 = current[0];
if (typeof match$4 === "number") {
return List.rev(tokens);
} else if (match$4.tag) {
return List.rev(tokens);
} else {
_current = /* Some */[/* Number */Block.__(0, [match$4[0] + $$String.make(1, head)])];
_input = tail;
continue ;
}
} else {
_current = /* Some */[/* Number */Block.__(0, [$$String.make(1, head)])];
_input = tail;
continue ;
}
} else {
return List.rev(tokens);
}
} else {
exit = 1;
}
} else if (head > 122 || head < 97) {
return List.rev(tokens);
} else if (current) {
var match$5 = current[0];
if (typeof match$5 === "number") {
return List.rev(tokens);
} else if (match$5.tag === 2) {
_current = /* Some */[/* Name */Block.__(2, [match$5[0] + $$String.make(1, head)])];
_input = tail;
continue ;
} else {
return List.rev(tokens);
}
} else {
_current = /* Some */[/* Name */Block.__(2, [$$String.make(1, head)])];
_input = tail;
continue ;
}
} else if (head >= 11) {
if (head !== 13) {
return List.rev(tokens);
} else {
exit = 1;
}
} else if (head >= 9) {
exit = 1;
} else {
return List.rev(tokens);
}
}
if (exit === 1) {
if (current) {
return List.rev(tokens);
} else {
_current = /* None */0;
_input = tail;
continue ;
}
}
} else {
return List.rev(tokens);
}
};
}
function printToken(token) {
if (typeof token === "number") {
if (token) {
return "CloseParen";
} else {
return "OpenParen";
}
} else {
switch (token.tag | 0) {
case 0 :
return "Number " + token[0];
case 1 :
return "String " + token[0];
case 2 :
return "Name " + token[0];
}
}
}
List.iter((function (k) {
console.log(printToken(k));
return /* () */0;
}), tokenizer("(add 2 (subtract 4 2))"));
var machine = /* record */[
/* current : None */0,
/* parsed : [] */0
];
exports.machine = machine;
exports.explode = explode;
exports.tokenizer = tokenizer;
exports.printToken = printToken;
/* Not a pure module */

@ -1,7 +1,12 @@
{
"name": "the-super-tiny-compiler",
"version": "1.0.0",
"author": "James Kyle <me@thejameskyle.com> (thejameskyle.com)",
"license": "CC-BY-4.0",
"main": "./the-super-tiny-compiler.js"
"scripts": {
"build": "bsb -make-world",
"start": "bsb -make-world -w",
"clean": "bsb -clean-world"
},
"devDependencies": {
"bs-platform": "1.9.2"
}
}

@ -0,0 +1,68 @@
type token =
| OpenParen
| CloseParen
| Number string
| String string
| Name string;
type tokenMachine = {
current: option token,
parsed: list token
};
let machine = {current: None, parsed: []};
let explode s => {
let rec exp i l =>
if (i < 0) {
l
} else {
exp (i - 1) [s.[i], ...l]
};
exp (String.length s - 1) []
};
let tokenizer input => {
let rec tok input current tokens =>
switch input {
| [] => List.rev tokens
| _ =>
let head = List.hd input;
let tail = List.tl input;
let next = tok tail;
switch (head, current, tokens) {
/* State: None */
| ('(', None, t) => next None [OpenParen, ...t]
| (')', None, t) => next None [CloseParen, ...t]
| (' ' | '\t' | '\r' | '\n', None, t) => next None t
| ('"', None, t) => next (Some (String "")) t
| ('0'..'9' as i, None, t) => next (Some (Number (String.make 1 i))) t
| ('a'..'z' as i, None, t) => next (Some (Name (String.make 1 i))) t
/* State: String */
| ('"', Some (String c), t) => next None [String c, ...t] /* TODO allow escaped double quotes :) */
| (i, Some (String c), t) => next (Some (String (c ^ String.make 1 i))) t
/* State: Number */
| ('0'..'9' as i, Some (Number c), t) => next (Some (Number (c ^ String.make 1 i))) t
| (')', Some (Number c), t) => next None [CloseParen, Number c, ...t]
| (' ', Some (Number c), t) => next None [Number c, ...t]
/* State: Name */
| ('a'..'z' as i, Some (Name c), t) => next (Some (Name (c ^ String.make 1 i))) t
| (')', Some (Name c), t) => next None [CloseParen, Name c, ...t]
| (' ', Some (Name c), t) => next None [Name c, ...t]
/* Errors */
| (_, _, t) => List.rev t /* TODO: handle errors */
}
};
tok (explode input) machine.current machine.parsed
};
let printToken token =>
switch token {
| OpenParen => "OpenParen"
| CloseParen => "CloseParen"
| Number s => "Number " ^ s
| String s => "String " ^ s
| Name s => "Name " ^ s
};
List.iter (fun k => Js.log (printToken k)) (tokenizer "(add 2 (subtract 4 2))");

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save