Введение

Понять, как создать язык программирования с нуля. Давайте создадим простой язык, который будет преобразован в JavaScript, а затем будет выполняться компилятором.

Начиная

Вот пример нашего синтаксиса.

let x be 2
let y be 8
update x to 4
if x > y
    print x
else
    print y

Вывод в JavaScript будет таким…

var x = 2;
var y = 8;
x = 4;
if (x > y) {
    console.log(x);
}
else {
    console.log(y);
}

Построить транспиллер

Транспилер - это переводчик исходного текста, который преобразует исходный код одного языка в исходный код другого. Давайте воспользуемся JavaScript, чтобы преобразовать наш язык в JavaScript.

Во-первых, напишите функцию JavaScript, которая сможет разделить исходный код нашего языка, не мешая кавычкам и скобкам.

const splitter = value => new RegExp(“\\s*” + value + “\\s*(?=(?:[^\”]*\”[^\”]*\”)*[^\”]*$)(?![^\\(\\[\\{]*[\\}\\]\\)])”, “g”);

Затем напишите еще одну функцию, которая поможет обрезать и удалять нежелательные внешние пробелы в нашем исходном коде.

const clear = value => value.replace(/^\s*([\s\S]*?)\s*$/, function(m, v) { return v; });

Затем напишите функцию, которая будет разделять каждую строку.

const lines = (value, tab = 0) => value.split(splitter(“\\n(?=\\s{“ + tab + “}\\w+)”)).filter(Boolean).map(value => clear(value));

Теперь давайте напишем функцию, которая будет токенизировать каждую строку нашего исходного кода, а затем преобразовывать ее в JavaScript.

const line = (value, tab = 0) => {
    let output = new String(), keyword = new String(), variable = new String(), operator = new String();
    const stack = new Array(), element = value.split(splitter(“\\s+”)), size = element.length;
    for (let position = 0; position < size; position++) {
        const token = element[position];
        if (position == 0) keyword = token;
        if (keyword == “remark”) {
            if (position > 0) stack.push(token);
            output = [“//”, stack.join(“ “)].join(“ “);
        } else if (keyword == “print”) {
            if (position > 0) stack.push(token);
            output = [“console.log”, “(“, stack.join(“ “), “)”].join(“”) + “;”;
        } else if (keyword == “let”) {
            if (position == 1) variable = token;
            if (position == 2) operator = (token == “be” ? “=” : token);
            if (position > 2) stack.push(token);
            output = [“var”, variable, operator, stack.join(“ “)].join(“ “) + “;”;
        } else if (keyword == “update”) {
            if (position == 1) variable = token;
            if (position == 2) operator = (token == “to” ? “=” : token);
            if (position > 2) stack.push(token);
            output = [variable, operator, stack.join(“ “)].join(“ “) + “;”;
        } else if (keyword == “if” || keyword == “else”) {
            if (position == 0) stack.push(token);
            if (position == 1 && token == “if”) stack.push(token);
            if (position == size — 1) {
                var item = lines(value, tab += 4); keyword = stack.join(“ “);
                var array = item.splice(1).map(v => (“ “).repeat(tab) + line(v, tab));
                var condition = [keyword, “(“ + clear(item.shift().replace(keyword, new String())) + “)”].join(“ “);
                output = [keyword == “else” ? keyword : condition, “{\n” + array.join(“\n”) + “\n” + (“ “).repeat(tab — 4) + “}”].join(“ “);
            }
        }
    }
    return output.toString();
};

Выполнить программу

Наконец, давайте перекомпилируем и выполним нашу программу.

const transpile = value => new Function(lines(value).map(v => line(v, 0)).join(“\n”));
const execute = value => transpile(value)();
console.log(transpite(“let x be 8\nprint x * 2”)); // test
execute(“let x be 8\nprint x * 2”); // test

Общий обзор

Теперь мы можем запустить программу, написанную на нашем языке. Если вы столкнулись с какой-либо проблемой. Вот полный проект, который вы можете скопировать и вставить в свой редактор кода, сохранить как index.html, а затем открыть его в веб-браузере.

Или получить на Github.

<!DOCTYPE html>
<html>
<head></head>
<body>
<script>
const clear = value => value.replace(/^\s*([\s\S]*?)\s*$/, function(m, v) { return v; });
const splitter = value => new RegExp(“\\s*” + value + “\\s*(?=(?:[^\”]*\”[^\”]*\”)*[^\”]*$)(?![^\\(\\[\\{]*[\\}\\]\\)])”, “g”);
const lines = (value, tab = 0) => value.split(splitter(“\\n(?=\\s{“ + tab + “}\\w+)”)).filter(Boolean).map(value => clear(value));
const line = (value, tab = 0) => {
    let output = new String(), keyword = new String(), variable = new String(), operator = new String();
    const stack = new Array(), element = value.split(splitter(“\\s+”)), size = element.length;
    for (let position = 0; position < size; position++) {
        const token = element[position];
        if (position == 0) keyword = token;
        if (keyword == “remark”) {
            if (position > 0) stack.push(token);
            output = [“//”, stack.join(“ “)].join(“ “);
        } else if (keyword == “print”) {
            if (position > 0) stack.push(token);
            output = [“console.log”, “(“, stack.join(“ “), “)”].join(“”) + “;”;
        } else if (keyword == “let”) {
            if (position == 1) variable = token;
            if (position == 2) operator = (token == “be” ? “=” : token);
            if (position > 2) stack.push(token);
            output = [“var”, variable, operator, stack.join(“ “)].join(“ “) + “;”;
        } else if (keyword == “update”) {
            if (position == 1) variable = token;
            if (position == 2) operator = (token == “to” ? “=” : token);
            if (position > 2) stack.push(token);
            output = [variable, operator, stack.join(“ “)].join(“ “) + “;”;
        } else if (keyword == “if” || keyword == “else”) {
            if (position == 0) stack.push(token);
            if (position == 1 && token == “if”) stack.push(token);
            if (position == size — 1) {
                var item = lines(value, tab += 4); keyword = stack.join(“ “);
                var array = item.splice(1).map(v => (“ “).repeat(tab) + line(v, tab));
                var condition = [keyword, “(“ + clear(item.shift().replace(keyword, new String())) + “)”].join(“ “);
                output = [keyword == “else” ? keyword : condition, “{\n” + array.join(“\n”) + “\n” + (“ “).repeat(tab — 4) + “}”].join(“ “);
            }
        }
    }
    return output.toString();
};
const transpile = value => new Function(lines(value).map(v => line(v, 0)).join(“\n”));
const execute = value => transpile(value)();
const source = `
let x be 2
let y be 8
update x to 4
if x > y
    print x
else
    print y
`;
console.log(transpile(source));
execute(source);
</script>
</body>
</html>

Следующие шаги

Надеюсь, что после этого руководства вы сможете создать свой собственный язык программирования и написать для него оптимизированный транспилятор с помощью JavaScript.

На следующем шаге я добавлю к нашему языку дополнительные элементы, такие как кросс-компилятор, чтобы преобразовать наш язык в несколько других языков программирования для Интернета, Android, iOS и Windows.

Не стесняйтесь отправить мне сообщение. Я буду рад помочь вам с чем угодно.

Вы можете связаться со мной по адресу [email protected]

Пожалуйста, поддержите меня на patreon.com/herikaniugu

Надеюсь, вам понравился этот пост.