[求助]Nodejs中有没有用 JS 做过语言的大侠, 怎样把 DSL 转化成代码?
[求助]Nodejs中有没有用 JS 做过语言的大侠, 怎样把 DSL 转化成代码?
想模仿 LispyScript 做一门很简单的语言, 然后编译到 JS, http://lispyscript.com/ 我主要想去掉很多括号, 效果, 可能像下面这样吧, 已经在尝试写了 https://gist.github.com/3617971 不会用 Jison 也不熟悉 Paser AST, 现在的代码是模仿 LispyScript 的 https://github.com/jiyinyiyong/scirpus/blob/gh-pages/src/to_code.coffee 先解析成 token, 然后直接把下面这样的 token 按模版编译成代码: http://jiyinyiyong.github.com/scirpus/html/aray.html 但是这样生成的代码用 esprima 梳理的时候发现经常代码会出错, 不知道现在有什么好的办法… 求指点…
当然可以!在 Node.js 中,你可以使用多种工具来将领域特定语言(DSL)转换为可执行代码。一个非常流行的选择是使用 nearley
和 nearley-tree
来解析 DSL 并生成抽象语法树(AST),然后通过模板或自定义逻辑将其转换为 JavaScript 代码。
示例
假设我们有一个简单的 DSL,它类似于 Lisp,但去掉了括号:
add 2 3
这应该被转换为:
function add(a, b) {
return a + b;
}
步骤 1: 安装必要的库
首先,你需要安装 nearley
和 nearley-tree
:
npm install nearley nearley-tree
步骤 2: 创建 Nearley 语法文件
创建一个名为 dsl.ne
的文件,定义 DSL 的语法:
@start = expression
expression
-> "add" number "and" number { result = { type: "add", left: $number0, right: $number1 } }
| number { result = $number }
number
-> /[0-9]+/
步骤 3: 解析并生成 AST
创建一个 JavaScript 文件来解析 DSL 并生成 AST:
const nearley = require('nearley');
const grammar = require('./dsl.ne');
const Parser = new nearley.Parser(nearley.Grammar.fromCompiled(grammar));
function parseDSL(dsl) {
try {
Parser.feed(dsl);
const ast = Parser.results[0];
return ast;
} catch (e) {
console.error(`Parse error: ${e.message}`);
return null;
}
}
const dsl = 'add 2 and 3';
const ast = parseDSL(dsl);
console.log(ast); // 输出: { type: 'add', left: '2', right: '3' }
步骤 4: 将 AST 转换为 JavaScript 代码
接下来,我们需要将 AST 转换为 JavaScript 代码:
function generateJS(ast) {
if (ast.type === 'add') {
return `function add(${ast.left}, ${ast.right}) { return ${ast.left} + ${ast.right}; }`;
} else {
return `return ${ast};`;
}
}
const jsCode = generateJS(ast);
console.log(jsCode); // 输出: function add(2, 3) { return 2 + 3; }
总结
以上步骤展示了如何使用 nearley
来解析 DSL 并生成 AST,然后通过简单的模板或自定义逻辑将其转换为 JavaScript 代码。这种方式提供了很大的灵活性,并且可以通过调整语法文件来支持更复杂的 DSL 规则。
希望这对你的项目有所帮助!
去掉括号之类的我觉得很coffee,javascript难看就在很多回调函数. 嘿嘿,你可以考虑加个关键字之后编译出来时异步回调的^ ^
操作 AST 我还不会啊, 瞟过 Mozilla 上的文档… 太难懂了… 我觉得所有 (跨行 or 行尾连续) 的括号都很难看, 这在 coffee 里也有点
你可以使用一种叫做解析器生成器(Parser Generator)的工具来帮助你将DSL转换为代码。一个常见的选择是使用Jison
。Jison
是一个JavaScript解析器生成器,它可以基于BNF(Backus-Naur Form)或Yacc文法生成解析器。
下面我会提供一个简单的例子,演示如何使用Jison
将DSL转换为JS代码。假设我们定义了一种DSL语言,它简化了函数调用语法:
DSL语法
add 1 2
subtract 3 4
这些DSL语句应该被转换为等价的JavaScript代码:
add(1, 2);
subtract(3, 4);
安装Jison
首先需要安装jison
库,可以通过npm来安装:
npm install jison --save
创建Jison文件
创建一个名为dsl.jison
的文件,并定义文法规则:
/* dsl.jison */
%lex
%%
[\t\n\r ]+ {/* skip whitespace */}
"add" {return 'ADD';}
"subtract" {return 'SUBTRACT';}
[0-9]+ {return 'NUMBER', yytext;}
<<EOF>> {return 'EOF';}
/lex
%start script
%%
script
: stmt EOF
{$$ = $1; }
;
stmt
: ADD NUMBER NUMBER
{ $$ = `add(${$2}, ${$3});`; }
| SUBTRACT NUMBER NUMBER
{ $$ = `subtract(${$2}, ${$3});`; }
;
编写转换逻辑
接下来,在你的Node.js项目中编写代码来使用Jison
编译并执行这个DSL:
const fs = require('fs');
const jison = require('jison');
const grammar = fs.readFileSync('./dsl.jison', 'utf8');
const parser = new jison.Generator(grammar);
// 解析并生成JavaScript代码
const input = 'add 1 2';
const result = parser.parse(input);
console.log(result); // 输出: add(1, 2);
通过这种方法,你可以使用Jison定义一个DSL的文法,然后将其转换为相应的JavaScript代码。如果你对更复杂的AST处理感兴趣,可以进一步学习如何处理和优化AST树。