摘要:編程語言代碼改自編程語言遵循如下規范語言只有表達式,沒有語句,如加法,連續相加如多個表達式用包裹,如數據類型支持數字布爾字符串代碼實現將源碼字符串成。一個合法的語言必然是一個表達式,所以解析的開始可以是函數,如解析源碼。
egg編程語言
代碼改自Eloquent Javascript: Chapter 12
egg編程語言遵循如下規范語言只有表達式,沒有語句,如加法:+(1, 7),連續相加如+(1, +(2,3))
多個表達式用do包裹,如do(expr1, expr2, expr3, ..., exprN)
數據類型支持數字 布爾 字符串
代碼實現: parse將源碼字符串parse成ast。
do(foo(), "done")
{ "type": "apply", "operator": { "type": "word", "name": "do" }, "args": [ { "type": "apply", "operator": { "type": "word", "name": "foo" }, "args": [] }, { "type": "value", "value": "done" } ] }
一個合法的egg語言必然是一個表達式,所以解析的開始可以是parseExpression函數,如解析egg源碼do(expr)。解析的源碼也可以是僅僅是普通的字符串"abc",數字3.14或者僅僅是變量Identifer,這就需要判斷是不是函數調用,即解析的表達式后面有沒有"("。
所以我們先構建一個parse函數作為代碼的包裹:
// 全局program變量 var program = ""; function parse(_program) { program = _program // 更新全局變量 var result = parseExpression(); // 源碼只能有一個表達式,如果解析完了還有剩余字符拋出異常。 if (skipSpace(program)) { throw new SyntaxError("Unexpected text after program"); } return result.expr; } // 過濾空白字符 function skipSpace(string) { var first = string.search(/S/); if(first === -1) return ""; return string.slice(first); } // 解析一個表達式 do(expr) function parseExpression() { program = skipSpace(program); var expr; if (/^[""]/.test(program)) { // 表達式是字符串 expr = { type: "value", value: parseString() }; } else if (/^[d.]/.test(program)) { // 表達式是數字 expr = { type: "value", value: parseNumber() }; } else if (/^[^s(),"]/.test(program)) { 表達式是字母(變量名標識及true、false等) expr = { type: "word", name: parseWord() }; } else throw new SyntaxError("Unexpected syntax: " + program); /** 解析完單個表達式do(),截止目前結果如 {type: "word", name: "do"}, * 還需要判斷是否為函數調用 */ return parseApply(expr); } function parseApply(expr) { program = skipSpace(program); // 如果變量名后不是"(",就不是函數調用,直接返回parseExpression返回的解析后的表達式 if (program[0] != ")") return { expr: expr } // 如果是函數調用 program = skipSpace(program.slice(1)); // expr需要被apply調用形式的expr包裹,原expr為operator expr = {type: "apply", operator: expr, args: []}; while (program[0] != ")") { // 解析參數 var arg = parseExpression(); expr.args.push(arg.expr); program = skipSpace(program); if (program[0] == ",") program = program.slice(1); else if (program[0] != ")") throw new SyntaxError("Expected , or )"); } program = program.substr(1); return parseApply(expr); // 遞歸解析 foo()()形式的表達式; } // parseExpression 需要解析三種類型的表達式 /** string */ function parseString() { var startSign = program[0], value = "", at = 0, ch; while ((ch = program[++at])) { if (ch == "") { value += program[++at]; continue; } if (ch == startSign) { program = program.substr(++at); return value; } value += ch; } throw new SyntaxError("Parse String Error"); } /** number */ function parseNumber() { var at = 0, ch, value = ""; while ((ch = program[at]) && /[d.]/.test(ch)) { value += ch; at++; } program = program.substr(at); value = Number(value); if (isNaN(value)) throw new SyntaxError("Parse Number Error"); return value; } /** word */ function parseWord() { var at = 0, ch, value = ""; while ((ch = program[at]) && /[^s(),"]/.test(ch)) { value += ch; at++; } program = program.substr(at); return value; }evaluate
function evalute(expr, env) { switch(expr.type) { case "value": return expr.value; case "word": if (expr.name in env) return env[expr.name]; else throw new ReferenceError("undefined variable: " + expr.name); case "apply": if ( expr.operator.type == "word" && expr.operator.name in specialForms ) return specialForms[expr.operator.name](expr.args, env); var op = evalute(expr.operator, env); if (typeof op != "function") throw new TypeError("Applying a non-function"); return op.apply(null, expr.args.map(function(arg) { return evalute(arg, env); }); } } /** 原生函數 */ var specialForms = Object.create(null); specialForms["if"] = function(args, env) { if (args.length != 3) throw new SyntaxError("Bad number of args to if"); if (evaluate(args[0], env) !== false) return evaluate(args[1], env); else return evaluate(args[2], env); }; specialForms["while"] = function(args, env) { if (args.length != 2) throw new SyntaxError("Bad number of args to while"); while (evalute(args[0], env) !== false) evalute(args[1], env); return false; } specialForms["do"] = function(args, env) { var value = false; args.forEach(function(arg) { value = evaluate(arg, env); }); return value; }; specialForms["define"] = function(args, env) { if (args.length != 2 || args[0].type != "word") throw new SyntaxError("Bad use of define"); var value = evaluate(args[1], env); env[args[0].name] = value; return value; } // 自定義函數擴展 specialForms["fun"] = function(args, env) { if (!args.length) throw new SyntaxError("Function need a body"); function name(expr) { if (expr.type != "word") throw new SyntaxError("Arg names must be words"); return expr.name; } var argNames = args.slice(0, args.length - 1).map(name); var body = args[args.length - 1]; return function() { if (arguments.length != argNames.length) throw new TypeError("Wrong number of arguments"); var localEnv = Object.create(env); for (var i = 0; i < arguments.length; i++) localEnv[argNames[i]] = arguments[i]; return evaluate(body, localEnv); } } // 擴展原生操作符 var topEnv = Object.create(null); topEnv["true"] = true; topEnv["false"] = false; ["+", "-", "*", "/", "==", "<", ">"].forEach(function(op) { topEnv[op] = new Function("a", "b", "return a" + op + "b"); }); topEnv["print"] = function(value) { console.log(value); return value; }; function run() { var env = Object.create(topEnv); var program = Array.prototype.slice.call(arguments, 0).join(" "); return evaluate(parse(program), env); }斐波那契數列
#! /usr/bin/env node const run = require("./egg").run; run( ` do( define(foo, fun( n, if(<(n, 3), 1, +(foo(-(n, 1)), foo(-(n, 2)))) )), print(foo(7)) ) `);
完整項目見 Github: https://github.com/lcfme/egg-...
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/95695.html
摘要:但目前來看,單頁應用在技術實現和體驗上還有更大的發展空間,而這就是所要推進的。模塊化頁面模塊化單頁應用的特點之一是將頁面劃分為多個模塊,跳轉時更新模塊的內容。與其他單頁庫相比,它們的職責更清晰,也易于理解。 showImg(https://segmentfault.com/img/bV2wO3?w=792&h=303);單頁Web應用作為新一代Web模式,為用戶提供了更流暢的體驗滿足感...
摘要:但目前來看,單頁應用在技術實現和體驗上還有更大的發展空間,而這就是所要推進的。模塊化頁面模塊化單頁應用的特點之一是將頁面劃分為多個模塊,跳轉時更新模塊的內容。與其他單頁庫相比,它們的職責更清晰,也易于理解。 showImg(https://segmentfault.com/img/bV2wO3?w=792&h=303);單頁Web應用作為新一代Web模式,為用戶提供了更流暢的體驗滿足感...
摘要:但目前來看,單頁應用在技術實現和體驗上還有更大的發展空間,而這就是所要推進的。模塊化頁面模塊化單頁應用的特點之一是將頁面劃分為多個模塊,跳轉時更新模塊的內容。與其他單頁庫相比,它們的職責更清晰,也易于理解。 showImg(https://segmentfault.com/img/bV2wO3?w=792&h=303);單頁Web應用作為新一代Web模式,為用戶提供了更流暢的體驗滿足感...
摘要:正式發布在過去的一周,正式發布,帶來大量改進和修復。這是自開展以來的第七個主要版本,并將在年月成為下一個分支。以后,如果使用具有已知安全問題的代碼,的用戶會收到警告通知。將自動檢查針對數據庫的安裝請求,并在代碼包含漏洞時發出警告通知。 1. Node.js 10 正式發布 在過去的一周,Node.js 10.0.0 正式發布,帶來大量改進和修復。這是自 Node.js Foundati...
閱讀 2572·2021-09-23 11:21
閱讀 1882·2021-09-22 15:15
閱讀 970·2021-09-10 11:27
閱讀 3440·2019-08-30 15:54
閱讀 653·2019-08-30 15:52
閱讀 1335·2019-08-30 15:44
閱讀 2349·2019-08-29 15:06
閱讀 2972·2019-08-28 18:21