怎样创造计算机语言,如何创建编译成JavaScript的编程语言

你曾经想过创建自己的编程语言吗?在本文中,我将演示如何使用免费工具和PEG.js解析器生成器快速编写编译为JavaScript的简单语言。

什么是解析器生成器

解析器生成器顾名思义就是一个基于语法、语言规范为程序员生成解析器的程序。用特定的语法写成。在本文中,我们将使用PEG.js解析器生成器,该生成器生成一个JavaScript文件,该文件将解析语言的代码并输出AST。

什么是AST

AST是抽象语法树的缩写。这是以工具可以理解的格式表示代码的方式。我们将使用Esprima格式的AST,这是一个输出AST的JavaScript解析器。

JavaScript代码生成

Esprima语法很酷的是,有一些工具可以根据他们的AST生成代码。一个例子是escodegen,它以Esprima AST作为输入和输出JavaScript代码。

9c2464867ce1d01eb2a557bb0aa8caf4.png

简单PEG.js解析器示例

在这里,我将展示如何为 if 语句创建简单的解析器语法。

PEG.js的语法并不复杂,它由规则的名称组成,而不是从规则中执行和返回的JavaScript的匹配和块。

以下是PEG.js文档提供的简单示例:

{ function makeInteger(o) { return parseInt(o.join(""), 10); }} start = additiveadditive = left:multiplicative "+" right:additive { return left + right; } / multiplicativemultiplicative = left:primary "*" right:multiplicative { return left * right; } / primary primary = integer / "(" additive:additive ")" { return additive; }integer "integer" = digits:[0-9]+ { return makeInteger(digits); }

它可以解析和计算简单的算术表达式示例是

10+2*3

,它计算到16。可以在PEG.js在线工具上测试此解析器。

但是我们需要的不是解释代码,返回一个值,而是返回Esprima AST。要查看Esprima AST的外观,可以检查AST资源管理器,选择Esprima作为输出并键入一些JavaScript。

下面以这样的简单代码为例:

if (foo == "bar") { 10 + 10 10 * 20}

JSON格式的输出如下:

{ "type": "Program", "body": [ { "type": "IfStatement", "test": { "type": "BinaryExpression", "operator": "==", "left": { "type": "Identifier", "name": "foo", "range": [ 4, 7 ] }, "right": { "type": "Literal", "value": "bar", "raw": "\"bar\"", "range": [ 11, 16 ] }, "range": [ 4, 16 ] }, "consequent": { "type": "BlockStatement", "body": [ { "type": "ExpressionStatement", "expression": { "type": "BinaryExpression", "operator": "+", "left": { "type": "Literal", "value": 10, "raw": "10", "range": [ 23, 25 ] }, "right": { "type": "Literal", "value": 10, "raw": "10", "range": [ 28, 30 ] }, "range": [ 23, 30 ] }, "range": [ 23, 30 ] }, { "type": "ExpressionStatement", "expression": { "type": "BinaryExpression", "operator": "*", "left": { "type": "Literal", "value": 10, "raw": "10", "range": [ 34, 36 ] }, "right": { "type": "Literal", "value": 20, "raw": "20", "range": [ 39, 41 ] }, "range": [ 34, 41 ] }, "range": [ 34, 41 ] } ], "range": [ 18, 43 ] }, "alternate": null, "range": [ 0, 43 ] } ], "sourceType": "module", "range": [ 0, 43 ]}

你不需要关心“范围”和“原始”。解析器输出的部分。

让我们把JSON分成它的一部分:

3c17c0f73791fa9ebbbc449458704c3e.png

if语句

if语句需要格式:

{ "type": "IfStatement", "test": { }, "consequent": { }, "alternate": null}

其中“测试”和“后果”是任何表达式:

if语句条件

条件可以是任何表达式,但在这里我们将有一个二进制表达式,可以比较两件事:

{ "type": "BinaryExpression", "operator": "==", "left": {}, "right": {}}

变量

变量使用率如下:

{ "type": "Identifier", "name": "foo"}

字面字符串

我们代码中使用的字面字符串如下:

{ "type": "Literal", "value": "bar"}

用支架块

if里面的块是这样的创建:

{ "type": "BlockStatement", "body": [ ]}

整个程序

而整个程序都是这样创建的:

{ "type": "Program", "body": [ ]}

PEG 解析器,用于编译为 JavaScript 的自己的语言

对于我们的演示语言,我们将创建类似于这样的代码:

if foo = "bar" then 10 + 10 10 * 20end

我们将创建 AST,然后创建 JavaScript 代码。

if的语法如下所示:

if = "if" _ expression:(comparison / expression) _ "then" body:(statements / _) _ "end" { return { "type": "IfStatement", "test": expression, "consequent": { "type": "BlockStatement", "body": body }, "alternate": null };}

我们有“if”令牌,那么比较或表达式,正文是语句或空格。

比较看起来是这样的:

comparison = _ left:expression _ "==" _ right:expression _ { return { "type": "BinaryExpression", "operator": "==", "left": left, "right": right };}

表达是这样的:

expression = expression:(variable / literal) { return expression; }

变量由三条规则创建:

variable = !keywords variable:name { return { "type": "Identifier", "name": variable }} keywords = "if" / "then" / "end" name = [A-Z_$a-z][A-Z_a-z0-9]* { return text(); }

现在我们来看下语句:

statements = _ head:(if / expression_statement) _ tail:(!"end" _ (if / expression_statement))* { return [head].concat(tail.map(function(element) { return element[2]; })); } expression_statement = expression:expression { return { "type": "ExpressionStatement", "expression": expression };}

最后一件事是字面意思:

literal = value:(string / Integer) { return {"type": "Literal", "value": value };} string = "\"" ([^"] / "\\\\\"")* "\"" { return JSON.parse(text());}Integer "integer" = _ [0-9]+ { return parseInt(text(), 10); }

这就是生成 AST 的整个解析器。在我们有了Esprima AST后,我们要做的就是使用escodegen生成代码。

生成 AST 并创建 JavaScript 代码的代码如下:

const ast = parser.parse(code);const js_code = escodegen.generate(ast);

解析器变量是使用PEG.js生成解析器时给出的名称。

这是我用来编写解析器的简单演示,可以使用语法,并为编译成JavaScript的自己的编程语言生成不同的语法。

1d967d4e0e676b95ff5d834325776e74.png

解析器生成器演示

这个简单的应用程序将代码保存在LocalStorage中,如果编译时没有错误,则每次更改。因此,可以安全地使用它创建自己的语言。

好了,本文到此结束。如果对编程、计算机、程序员方面感兴趣的话,欢迎私信联系我,随时交流!点个关注,是对我莫大的鼓励!

举报/反馈

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值