javascript数组解析匹配

javascript数组解析匹配,javascript,logic,pattern-matching,expression,Javascript,Logic,Pattern Matching,Expression,假设我有一个数组 ["red", "blue", "neon", "black", "orange"] 我想评估某个匹配模式是否正确 我想用逗号表示或和&&表示和 "red&&blue" -> true "blue&&white" -> false "red,white" -> true "(red&&blue),(red&&white)" -> true "(red&&blue)&

假设我有一个数组

["red", "blue", "neon", "black", "orange"]
我想评估某个匹配模式是否正确

我想用逗号表示或和&&表示和

"red&&blue" -> true
"blue&&white" -> false
"red,white" -> true
"(red&&blue),(red&&white)" -> true
"(red&&blue)&&(red&&white)" -> false
"(red&&blue)&&(red&&neon)" -> true
我应该使用什么样的匹配方案?我不希望从头开始实现解析器,如果有任何现有的解析器的话,这将是非常好的,但是我希望逻辑的工作方式与javascript中的工作方式一样,具有无限的复杂性

我基本上是在寻找类似的东西,但对于javascript:

几乎可以肯定,最好是编写一个解析器或使用别人已经编写的解析器。正如您在评论中指出的,对于这种非常有限的输入,实际上非常简单:

  • 在运算符上拆分字符串
  • 遍历生成的拆分字符串:
    • 验证运算符
    • 转换为
      |
    • 可选地验证名称
    • 将名称替换为
      true
      (如果在数组中)或
      false
      (如果不在数组中)
  • 再次将结果重新连接到字符串中
  • 通过
    eval
    运行结果(因为您现在知道它只有有您列出的运算符和文本
    true
    false
这里有一个概念的快速证明:|

类似地,这会将该数组转换为具有以下命名属性的对象:

var obj = {};
data.forEach(function(entry) {
    obj[entry] = true;
});
…然后您可能会将其传递到表达式计算器

如果您要执行
eval
路径,您必须对字符串做更多的准备,将
“(红色和蓝色)、(红色和白色)”
转换为
”(obj[“红色”]&&obj[“蓝色”])|(obj[“红色”]&&obj[“白色”])”
,如下所示:

str = str.replace(/,/g, "||").replace(/\b([a-zA-Z0-9_]+)\b/g, 'obj["$1"]');
{
var props = ["red", "blue", "neon", "black", "orange"]; 
}


start
  = additive

additive
  = left:multiplicative "," right:additive { return left || right }
  / multiplicative

multiplicative
  = left:primary "&&" right:multiplicative { return left && right }
  / primary

primary
  = atom
  / "(" additive:additive ")" { return additive; }

atom 
  = letters:[a-z]+ { return props.indexOf(letters.join("")) >= 0 }
我不会使用表达式求值器库来做一个示例,但下面是
eval
的基本知识:


表达方式
.好{
颜色:绿色;
}
.不好{
颜色:#d22;
}
(功能(){
var数据=[“红色”、“蓝色”、“霓虹灯”、“黑色”、“橙色”];
var测试=[
{expr:“红色和蓝色”,expect:true},
{expr:“蓝色和白色”,expect:false},
{expr:“红色,白色”,expect:true},
{expr:“(红色和蓝色),(红色和白色)”,expect:true},
{expr:“(红色和蓝色)和(红色和白色)”,expect:false},
{expr:“(红色和蓝色)和(红色和霓虹灯)”,期望值:true}
];
var-obj;
//将数据转换为具有命名属性的对象
obj={};
data.forEach(函数(条目){
obj[输入]=真;
});
//将表达式转换为eval字符串
测试。forEach(createValstring);
//运行测试
测试。forEach(runTest);
函数createValString(测试){
test.evalStr=test.expr.replace(/,/g,“| |”)。replace(/\b([a-zA-Z0-9|]+)\b/g,'obj[“$1”]”);
}
函数运行测试(test){
var结果;
显示(test.evalStr);
结果=!!eval(test.evalStr);//依赖于我们关闭'obj'`
显示(test.expr+”:获取“+result+”,预期“+test.expect,result==test.expect);
}
功能显示(消息,良好){
var p=document.createElement('p');
p、 innerHTML=字符串(msg);
如果(良好类型!=“未定义”){
p、 className=好?“好”:“坏”;
}
文件.正文.附件(p);
}
})();

这只是一个起点。首先,在转换字符串并将其与
eval

一起使用之前,您需要仔细检查字符串。您几乎可以肯定,最好编写一个解析器或使用别人已经编写的解析器。正如您在评论中指出的,对于这种非常有限的输入,实际上非常简单:

  • 在运算符上拆分字符串
  • 遍历生成的拆分字符串:
    • 验证运算符
    • 转换为
      |
    • 可选地验证名称
    • 将名称替换为
      true
      (如果在数组中)或
      false
      (如果不在数组中)
  • 再次将结果重新连接到字符串中
  • 通过
    eval
    运行结果(因为您现在知道它只有有您列出的运算符和文本
    true
    false
这里有一个概念的快速证明:|

类似地,这会将该数组转换为具有以下命名属性的对象:

var obj = {};
data.forEach(function(entry) {
    obj[entry] = true;
});
…然后您可能会将其传递到表达式计算器

如果您要执行
eval
路径,您必须对字符串做更多的准备,将
“(红色和蓝色)、(红色和白色)”
转换为
”(obj[“红色”]&&obj[“蓝色”])|(obj[“红色”]&&obj[“白色”])”
,如下所示:

str = str.replace(/,/g, "||").replace(/\b([a-zA-Z0-9_]+)\b/g, 'obj["$1"]');
{
var props = ["red", "blue", "neon", "black", "orange"]; 
}


start
  = additive

additive
  = left:multiplicative "," right:additive { return left || right }
  / multiplicative

multiplicative
  = left:primary "&&" right:multiplicative { return left && right }
  / primary

primary
  = atom
  / "(" additive:additive ")" { return additive; }

atom 
  = letters:[a-z]+ { return props.indexOf(letters.join("")) >= 0 }
我不会使用表达式求值器库来做一个示例,但下面是
eval
的基本知识:


表达方式
.好{
颜色:绿色;
}
.不好{
颜色:#d22;
}
(功能(){
var数据=[“红色”、“蓝色”、“霓虹灯”、“黑色”、“橙色”];
var测试=[
{expr:“红色和蓝色”,expect:true},
{expr:“蓝色和白色”,expect:false},
{expr:“红色,白色”,expect:true},
{expr:“(红色和蓝色),(红色和白色)”,expect:true},
{expr:“(红色和蓝色)和(红色和白色)”,expect:false},
{expr:“(红色和蓝色)和(红色和霓虹灯)”,期望值:true}
];
var-obj;
//将数据转换为具有命名属性的对象
obj={};
data.forEach(函数(条目){
obj[输入]=真;
});
//将表达式转换为eval字符串
测试。forEach(createValstring);
//运行测试
测试。forEach(runTest);
函数createValString(测试){
test.evalStr=test.expr.replace(/,/g,“| |”)。replace(/\b([a-zA-Z0-9|]+)\b/g,'obj[“$1”]”);
}
函数运行测试(test){
var结果;
D
var whiteList = ["red", "blue", "neon", "black", "orange"];
function evaluator(inputString) {
    var data = whiteList.reduce(function(previous, current) {
        return previous.split(current).join("####");
    }, inputString);
    data = data.replace(",", "||").replace(/[a-zA-Z]+/g, "false");
    return eval(data.replace(/####/g, "true"));
}