Введение
Понять, как создать язык программирования с нуля. Давайте создадим простой язык, который будет преобразован в 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
Надеюсь, вам понравился этот пост.