1. firefly
  2. FireLang2

Commits

firefly  committed 34c9adf

Unbroke FireLang implementation :D. Also created a separate file, firelang.js.

  • Participants
  • Parent commits 82aab62
  • Branches default

Comments (0)

Files changed (4)

File src/floop.js

View file
 			switch (typeof a) {
 				case 'object': return isArray(a) ? sExpr(a) : (a ? a.value : a);
 			//	case 'function': return a();	// FIXME: DEBUGGING ONLY!
-				case 'function': return a.name;
+				case 'function': return a.ffName;
 				case 'string': return "'" + a + "'";
 				case 'number': return a;
 				default: return "<" + a + ">";
 		return tokens;
 	};
 	
-	Floop.tokenize = function(str) {
-		var tokens = [];
-		
-		for (var i=0; i<str.length; i++) {
-			var c = str.charAt(i);
-			
-			if (beginsIdentifier(c)) {
-				var start = i;
-				for (; isIdentifier(str.charAt(i)) && i<str.length; i++);
-				var end = i;
-				tokens.push(str.substring(start, end));
-				i--;
-			} else if (isNumber(c)) {
-				var start = i;
-				for (; isNumber(str.charAt(i)) && i<str.length; i++);
-				var end = i;
-				tokens.push(str.substring(start, end));
-				i--;
-			} else if (isWhitespace(c)) {
-				for (; isWhitespace(str.charAt(i)) && i<str.length; i++);
-				i--;
-			} else if (c == '"') {
-				var start = i;
-				for (i++; (str.charAt(i) != '"' || str.charAt(i-1) == "\\") && i<str.length; i++);
-				var end = i + 1;
-				tokens.push(str.substring(start, end));
-			} else {
-				tokens.push(str.substr(i, 1));
-			}
-		}
-		return tokens;
-	};
-	
 		/* ---------- Grouper ---------- */
 	function Grouper(isValue, getValue) {
 		this.isValue = isValue;

File src/floop.js~

View file
 		return tokens;
 	};
 	
-	Floop.tokenize = function(str) {
-		var tokens = [];
-		
-		for (var i=0; i<str.length; i++) {
-			var c = str.charAt(i);
-			
-			if (beginsIdentifier(c)) {
-				var start = i;
-				for (; isIdentifier(str.charAt(i)) && i<str.length; i++);
-				var end = i;
-				tokens.push(str.substring(start, end));
-				i--;
-			} else if (isNumber(c)) {
-				var start = i;
-				for (; isNumber(str.charAt(i)) && i<str.length; i++);
-				var end = i;
-				tokens.push(str.substring(start, end));
-				i--;
-			} else if (isWhitespace(c)) {
-				for (; isWhitespace(str.charAt(i)) && i<str.length; i++);
-				i--;
-			} else if (c == '"') {
-				var start = i;
-				for (i++; (str.charAt(i) != '"' || str.charAt(i-1) == "\\") && i<str.length; i++);
-				var end = i + 1;
-				tokens.push(str.substring(start, end));
-			} else {
-				tokens.push(str.substr(i, 1));
-			}
-		}
-		return tokens;
-	};
-	
 		/* ---------- Grouper ---------- */
 	function Grouper(isValue, getValue) {
 		this.isValue = isValue;
 				var match = op.match(tokens.slice(j));
 				
 				if (match) {
+					var nTree = match[0];
+					
 					if (op.isGroupTime) {
-						
+						nTree = nTree[0].apply(this, nTree.slice(1));
 					}
 					
-					tokens.splice(j, match[1], match[0]);
+					tokens.splice(j, match[1], nTree);
 					j -= match[1] - 1;
 				}
 			}

File src/interpreter.html

View file
 	<title>FireLang - firefly.nu</title>
 	<meta charset="UTF-8" />
 	<link rel="stylesheet" type="text/css" href="firelang.css" />
-	<script src="lib/json.js"></script>
 	<script src="floop.js"></script>
+	<script src="firelang.js"></script>
 	<script>
-	var indentation = 0;
 	function output(str) {
 		var space = "";
-		for (var i=0; i<indentation; i++) space += "   ";
+	//	for (var i=0; i<indentation; i++) space += "   ";
 		document.getElementById('debug').appendChild(document.createTextNode(
-				space + str + "\n"));
+				"" + str + "\n"));
 	}
 	
 	function firelangOutput(str, isError) {
 	}
 	
 		/* ---------- FireLang ---------- */
+	var Syntax = FireLang;
 	var FireLang = function(stdout) {
 		this.namespace = {};
 		
 		};
 	};
 	
+	for (var k in Syntax) FireLang[k] = Syntax[k];
+	
 	(function() {
-			/* Tokenizer and Grouper functions. */
-		function beginsIdentifier(c) {
-			return c >= "a" && c <= "z" || c >= "A" && c <= "Z" ||
-					c == "$" || c == "_";
-		}
-		function isNumber(c) {
-			return c >= "0" && c <= "9";
-		}
-		function isWhitespace(c) {
-			return c == " " || c == "\t" || c == "\n" || c == "\r";
-		}
-		function isIdentifier(c) {
-			return beginsIdentifier(c) || isNumber(c);
-		}
-		
-		function isValue(str) {
-			return typeof(str) == 'string' && (str.match(/^".*"$/) ||
-					str.match(/^[A-Za-z\d_$]\w*$/) || str.match(/^\d+/));
-		}
-
-		function getValue(obj) {
-			if (typeof(obj) != 'string') {
-				return obj;
-			} else if (obj.match(/^"(?:[^"]|(?=<\\)")*"$/)) {
-				return {value: obj.substr(1, obj.length-2)};
-			} else if (obj.match(/\d+/)) {
-				return {value: parseInt(obj)};
-			} else {
-				return obj;
-			}
-		}
-		
 			/* Helper functions */
 		function isArray(obj) {
 			return typeof(obj) == 'object' && obj !== null && obj instanceof Array;
 			}, args);
 		}
 		
-		var tokenizer = new Floop.Tokenizer();
-		tokenizer.add("identifier", beginsIdentifier, isIdentifier);
-		tokenizer.add("number", isNumber, isNumber);
-		tokenizer.add("string", function(c) {
-			return c == '"';
-		}, function(c, i, str) {
-			return i == 1 || (str.charAt(i-1) != '"' && str.charAt(i-2) != "\\");
-		});
-		tokenizer.add("whitespace", isWhitespace, isWhitespace, true);
-		tokenizer.add("operator", function() {return true;}, function() {return false;});
-		
 		FireLang.prototype.interpret = function(str) {
-			var stm = grouper.group(tokenizer.tokenize(str));
+			var stm = FireLang.grouper.group(FireLang.tokenizer.tokenize(str));
+			execute(this, stm);
 		};
-		
-		var grouper = new Floop.Grouper(isValue, getValue);
-		
-		function fun(name, func) {
-			func.name = name;
-			return func;
-		}
-		
-		function unwrap(tuple) {
-			if (typeof(tuple) == 'string') {
-				return [tuple];
-			} else if (typeof(tuple[1]) == 'object') {
-				return unwrap(tuple[1]).concat(tuple[2]);
-			} else {
-				return [tuple[1], tuple[2]];
-			}
-		}
-		
-		grouper.add(["(", {a: "value"}, ")"], fun("id", function(a) {
-			return a;
-		}), 1);
-		grouper.add(["function", {a: "tree"}, "{", {code: "tree"}, "}"], fun("fun", function(a, code) {
-			var args = unwrap(a[1]);
-			output("Defining function!");
-			output("  args: " + anyExpr(args));
-			output("  code: " + anyExpr(code));
-			
-			return {type: "function", args: args, code: code};
-		}), 2);
-		grouper.add([{a: "value"}, "+", {b: "value"}], fun("+", function(a, b) {
-			return a.value + b.value;
-		}), 4);
-		
-		grouper.add([{a: "value"}, {b: "value"}], fun("call", function(func, args) {
-			if (!func || (func.type != "function" && func.type != "function-builtin"))
-				throw new Error("Tried to call non-function '" + func + "'");
-			
-			if (args.type != "tuple") {
-				throw new Error("Calling function with non-tuple argument is currently unsupported.");
-			}
-			
-			if (func.type == "function-builtin") {
-				func.execute.apply(this, args.values);
-			} else {
-				for (var i=0; i<func.args.length; i++) {
-					this.namespace[func.args[i]] = args.values[i] || {value: "GAH undefined"};
-				}
-				
-				return this.execute(func.code);
-			}
-		}), 8);
-		
-		grouper.add([{a: "value"}, ",", {b: "value"}], fun("tuple", function(a, b) {
-			return {type: "tuple", values: [a, b]};
-		}), 9);
-		grouper.add([{x: "literal"}, "=", {a: "value"}], fun("assign", function(name, value) {
-			output("Assigning value! " + name + ": " + anyExpr(value));
-			this.namespace[name] = value;
-		}), 15);
-		grouper.add([{a: "value"}, ";", {b: "value"}], fun("sep", function(a, b) {
-			return b;
-		}), 16);
-		grouper.add([{a: "value"}, ";"], fun("sep", function(a) {
-			return a;
-		}), 16.1);
-		grouper.add([";", {a: "value"}], fun("sep", function(a) {
-			return a;
-		}), 16.2);
 	})();
 	
 	var interpreter = new FireLang(firelangOutput);
 	function interpret() {
 		document.getElementById('debug').innerHTML = "";
 		document.getElementById('stdout').innerHTML = "";
+		document.getElementById('error').innerHTML = "";
 		
-		var code = document.getElementById('input').value;
-		
-		interpreter.interpret(code);
-		
-		output(" ----");
-		for (var k in interpreter.namespace) {
-			output(k + ": " + interpreter.namespace[k]);
+		try {
+			var code = document.getElementById('input').value;
+			interpreter.interpret(code);
+			
+			output(" ----");
+			for (var k in interpreter.namespace) {
+				output(k + ": " + interpreter.namespace[k]);
+			}
+		} catch (err) {
+			document.getElementById('error').innerHTML = "Error: " + err.message;
 		}
 	}
 	
 	function init() {
-		hide("debug");
+	//	hide("debug");
 		interpret();
 	}
 	
 		<pre id="debug"></pre>
 	</div>
 	
+	<div class="wrapper">
+		<h2>Error</h2>
+		<div class="hider" onclick="showHide('error')"></div>
+		<pre id="error"></pre>
+	</div>
+	
 	<span id="footer">&copy; Jonas Höglund 2010</span>
 </body>
 </html>

File src/interpreter.html~

View file
 	<title>FireLang - firefly.nu</title>
 	<meta charset="UTF-8" />
 	<link rel="stylesheet" type="text/css" href="firelang.css" />
-	<script src="lib/json.js"></script>
 	<script src="floop.js"></script>
+	<script src="firelang.js"></script>
 	<script>
-	var indentation = 0;
 	function output(str) {
 		var space = "";
-		for (var i=0; i<indentation; i++) space += "   ";
+	//	for (var i=0; i<indentation; i++) space += "   ";
 		document.getElementById('debug').appendChild(document.createTextNode(
-				space + str + "\n"));
+				"" + str + "\n"));
 	}
 	
 	function firelangOutput(str, isError) {
 	}
 	
 		/* ---------- FireLang ---------- */
+	var Syntax = FireLang;
 	var FireLang = function(stdout) {
 		this.namespace = {};
 		
 		};
 	};
 	
+	for (var k in Syntax) FireLang[k] = Syntax[k];
+	
 	(function() {
-			/* Tokenizer and Grouper functions. */
-		function beginsIdentifier(c) {
-			return c >= "a" && c <= "z" || c >= "A" && c <= "Z" ||
-					c == "$" || c == "_";
-		}
-		function isNumber(c) {
-			return c >= "0" && c <= "9";
-		}
-		function isWhitespace(c) {
-			return c == " " || c == "\t" || c == "\n" || c == "\r";
-		}
-		function isIdentifier(c) {
-			return beginsIdentifier(c) || isNumber(c);
-		}
-		
-		function isValue(str) {
-			return typeof(str) == 'string' && (str.match(/^".*"$/) ||
-					str.match(/^[A-Za-z\d_$]\w*$/) || str.match(/^\d+/));
-		}
-
-		function getValue(obj) {
-			if (typeof(obj) != 'string') {
-				return obj;
-			} else if (obj.match(/^"(?:[^"]|(?=<\\)")*"$/)) {
-				return {value: obj.substr(1, obj.length-2)};
-			} else if (obj.match(/\d+/)) {
-				return {value: parseInt(obj)};
-			} else {
-				return obj;
-			}
-		}
-		
 			/* Helper functions */
 		function isArray(obj) {
 			return typeof(obj) == 'object' && obj !== null && obj instanceof Array;
 			}, args);
 		}
 		
-		var tokenizer = new Floop.Tokenizer();
-		tokenizer.add("identifier", beginsIdentifier, isIdentifier);
-		tokenizer.add("number", isNumber, isNumber);
-		tokenizer.add("string", function(c) {
-			return c == '"';
-		}, function(c, i, str) {
-			return i == 1 || str.charAt(i-1) != '"';
-		});
-		tokenizer.add("whitespace", isWhitespace, isWhitespace, true);
-		tokenizer.add("operator", function() {return true;}, function() {return false;});
-		
 		FireLang.prototype.interpret = function(str) {
-			var stm = grouper.group(tokenizer.tokenize(str));
+			var stm = FireLang.grouper.group(FireLang.tokenizer.tokenize(str));
+			execute(this, stm);
 		};
-		
-		var grouper = new Floop.Grouper(isValue, getValue);
-		
-		function fun(name, func) {
-			func.name = name;
-			return func;
-		}
-		
-		function unwrap(tuple) {
-			if (typeof(tuple) == 'string') {
-				return [tuple];
-			} else if (typeof(tuple[1]) == 'object') {
-				return unwrap(tuple[1]).concat(tuple[2]);
-			} else {
-				return [tuple[1], tuple[2]];
-			}
-		}
-		
-		grouper.add(["(", {a: "value"}, ")"], fun("id", function(a) {
-			return a;
-		}), 1);
-		grouper.add(["function", {a: "tree"}, "{", {code: "tree"}, "}"], fun("fun", function(a, code) {
-			var args = unwrap(a[1]);
-			output("Defining function!");
-			output("  args: " + anyExpr(args));
-			output("  code: " + anyExpr(code));
-			
-			return {type: "function", args: args, code: code};
-		}), 2);
-		grouper.add([{a: "value"}, "+", {b: "value"}], fun("+", function(a, b) {
-			return a.value + b.value;
-		}), 4);
-		
-		grouper.add([{a: "value"}, {b: "value"}], fun("call", function(func, args) {
-			if (!func || (func.type != "function" && func.type != "function-builtin"))
-				throw new Error("Tried to call non-function '" + func + "'");
-			
-			if (args.type != "tuple") {
-				throw new Error("Calling function with non-tuple argument is currently unsupported.");
-			}
-			
-			if (func.type == "function-builtin") {
-				func.execute.apply(this, args.values);
-			} else {
-				for (var i=0; i<func.args.length; i++) {
-					this.namespace[func.args[i]] = args.values[i] || {value: "GAH undefined"};
-				}
-				
-				return this.execute(func.code);
-			}
-		}), 8);
-		
-		grouper.add([{a: "value"}, ",", {b: "value"}], fun("tuple", function(a, b) {
-			return {type: "tuple", values: [a, b]};
-		}), 9);
-		grouper.add([{x: "literal"}, "=", {a: "value"}], fun("assign", function(name, value) {
-			output("Assigning value! " + name + ": " + anyExpr(value));
-			this.namespace[name] = value;
-		}), 15);
-		grouper.add([{a: "value"}, ";", {b: "value"}], fun("sep", function(a, b) {
-			return b;
-		}), 16);
-		grouper.add([{a: "value"}, ";"], fun("sep", function(a) {
-			return a;
-		}), 16.1);
-		grouper.add([";", {a: "value"}], fun("sep", function(a) {
-			return a;
-		}), 16.2);
 	})();
 	
 	var interpreter = new FireLang(firelangOutput);
 	function interpret() {
 		document.getElementById('debug').innerHTML = "";
 		document.getElementById('stdout').innerHTML = "";
+		document.getElementById('error').innerHTML = "";
 		
-		var code = document.getElementById('input').value;
-		
-		interpreter.interpret(code);
-		
-		output(" ----");
-		for (var k in interpreter.namespace) {
-			output(k + ": " + interpreter.namespace[k]);
+		try {
+			var code = document.getElementById('input').value;
+			interpreter.interpret(code);
+			
+			output(" ----");
+			for (var k in interpreter.namespace) {
+				output(k + ": " + interpreter.namespace[k]);
+			}
+		} catch (err) {
+			document.getElementById('error').innerHTML = "Error: " + err.message;
 		}
 	}
 	
 	function init() {
-		hide("debug");
+	//	hide("debug");
 		interpret();
 	}
 	
 		<pre id="debug"></pre>
 	</div>
 	
+	<div class="wrapper">
+		<h2>Error</h2>
+		<div class="hider" onclick="showHide('error')"></div>
+		<pre id="error"></pre>
+	</div>
+	
 	<span id="footer">&copy; Jonas Höglund 2010</span>
 </body>
 </html>