我正在使用Peg.js实现一个关系代数到SQL转换器。我实现了几乎所有操作,但我没有实现分配运算符,其中关系转换为SQL并保存在变量中以供将来使用。 (例如:A< - Πid(客户))。
由于原始代码有超过200行,我将发布一个简单的例子来解释我曾想过捕获这条规则的内容。
解析器的代码:
{
var variables = [];
console.log(variables);
function save(chave, value, rest){
console.log("save", chave, value);
variables[chave] = value;
return rest;
}
function get(chave){
console.log("get", chave);
return variables[chave];
}
}
start
= _ id:Identificador _ "=" _ val:Integer _ [\n]* _ rest:start
{save(id,val);}
/ _ val:Integer _ {return val;}
/ _ id:Identificador _ {console.log(id, variables[id]); return get(id);}
Identificador "identificador"
= [a-zA-Z]+ {return text();}
Integer "integer"
= [0-9]+ { return parseInt(text(), 10); }
_ "whitespace"
= [ \t\r]*
输入示例:
A = 23
B = 45
A
在我的解析器的开头,我创建了一个数组来存储要保存的值,这些值可以通过变量名来访问。
在我的第一条规则中,我说过每个标识符,后跟赋值运算符(在我的例子中,是等号),然后是要保存的值(在示例中是一个整数),然后是换行然后对于文本的其余部分,将在数组中保存,将标识符存储为键及其值,并处理查询的其余部分。
在第一条规则的最后一行,我声明任何只包含字母标识符的行都将被其存储的值替换。在该示例中,解析器应返回值23,该值是分配给变量A的值。
然而,解析器正在返回undefined
。我检查了Web控制台,发现执行顺序不正确。
Console after running the parser
有没有办法设置确切的执行顺序?我希望解析器在处理文本的其余部分之前保存找到的值。
答案 0 :(得分:1)
我不确定如何使peg颠倒评估顺序,但是你可以将所有表达式抛出到堆栈中,然后以相反的顺序对它们进行评估。试试这个:
{
var stack = [];
var result = null;
var variables = {};
console.log(variables);
function save(chave, value, rest){
console.log("save", chave, value);
stack.push(()=>{variables[chave] = value});
return rest;
}
function get(chave){
console.log("get", chave);
stack.push(()=>{result = variables[chave]});
}
function evalStack() {
for (var i = stack.length - 1; 0 <= i; i--) {
stack[i]()
}
return result;
}
}
start
= expr
{return evalStack();}
expr
= _ id:Identificador _ "=" _ val:Integer _ [\n]* _ rest:expr
{save(id,val);}
/ _ val:Integer _ {return val;}
/ _ id:Identificador _ {console.log(id, variables[id]); return get(id);}
Identificador "identificador"
= [a-zA-Z]+ {return text();}
Integer "integer"
= [0-9]+ { return parseInt(text(), 10); }
_ "whitespace"
= [ \t\r]*