国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

用JS創造一個全新的編程語言

muzhuyu / 3160人閱讀

摘要:編程語言代碼改自編程語言遵循如下規范語言只有表達式,沒有語句,如加法,連續相加如多個表達式用包裹,如數據類型支持數字布爾字符串代碼實現將源碼字符串成。一個合法的語言必然是一個表達式,所以解析的開始可以是函數,如解析源碼。

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

相關文章

  • 全新單頁JavaScript框架Amaple

    摘要:但目前來看,單頁應用在技術實現和體驗上還有更大的發展空間,而這就是所要推進的。模塊化頁面模塊化單頁應用的特點之一是將頁面劃分為多個模塊,跳轉時更新模塊的內容。與其他單頁庫相比,它們的職責更清晰,也易于理解。 showImg(https://segmentfault.com/img/bV2wO3?w=792&h=303);單頁Web應用作為新一代Web模式,為用戶提供了更流暢的體驗滿足感...

    djfml 評論0 收藏0
  • 全新單頁JavaScript框架Amaple

    摘要:但目前來看,單頁應用在技術實現和體驗上還有更大的發展空間,而這就是所要推進的。模塊化頁面模塊化單頁應用的特點之一是將頁面劃分為多個模塊,跳轉時更新模塊的內容。與其他單頁庫相比,它們的職責更清晰,也易于理解。 showImg(https://segmentfault.com/img/bV2wO3?w=792&h=303);單頁Web應用作為新一代Web模式,為用戶提供了更流暢的體驗滿足感...

    yanwei 評論0 收藏0
  • 全新單頁JavaScript框架Amaple

    摘要:但目前來看,單頁應用在技術實現和體驗上還有更大的發展空間,而這就是所要推進的。模塊化頁面模塊化單頁應用的特點之一是將頁面劃分為多個模塊,跳轉時更新模塊的內容。與其他單頁庫相比,它們的職責更清晰,也易于理解。 showImg(https://segmentfault.com/img/bV2wO3?w=792&h=303);單頁Web應用作為新一代Web模式,為用戶提供了更流暢的體驗滿足感...

    wemallshop 評論0 收藏0
  • FCC 成都社區·前端周刊 第 10 期

    摘要:正式發布在過去的一周,正式發布,帶來大量改進和修復。這是自開展以來的第七個主要版本,并將在年月成為下一個分支。以后,如果使用具有已知安全問題的代碼,的用戶會收到警告通知。將自動檢查針對數據庫的安裝請求,并在代碼包含漏洞時發出警告通知。 1. Node.js 10 正式發布 在過去的一周,Node.js 10.0.0 正式發布,帶來大量改進和修復。這是自 Node.js Foundati...

    BigNerdCoding 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<