Если вы просто хотите, чтобы разобрать вашу строку, то есть много JavaScript разбора библиотеки, которые могут сделать это для вас. Например, вы можете разобрать действительный Код JavaScript, используя acorn в Mozilla AST. Вы также можете преобразовать его обратно в строку, используя escodegen.
К сожалению, ваша строка не является действительным кодом JavaScript, но если вы удалите if
в начале каждой строки, вы можете определенно проанализировать строку, используя acorn. Выход будет AST, который не является тем, что вы ищете, но вы можете легко преобразовать его в желаемый формат.
Использование полнофункционального анализатора, однако для такого тривиального варианта использования, по моему скромному мнению, является излишним. Например, если вы просто хотите, чтобы оценить вашу строку, то вы можете использовать Function
конструктор следующим образом:
function read(expression) {
var variables = expression.match(/\$\w+/g);
var length = variables.length;
var uniqueVariables = [];
var index = 0;
while (index < length) {
var variable = variables[index++];
if (uniqueVariables.indexOf(variable) < 0)
uniqueVariables.push(variable);
}
return Function.apply(null, uniqueVariables.concat("return " + expression));
}
Эта read
функция позволяет читать выражения следующим образом:
var condition = read("$a == 10 && ($b == '5' || $c == 'test')");
Теперь вы можете использовать condition
функции следующим образом:
alert(condition(10, "10", "test")); // true
alert(condition(5, "10", "test")); // false
Смотрите демо для себя: http://jsfiddle.net/ZnUh2/
Конечно, вам нужно удалить if
в начале всех ваших строк, чтобы их прочитать.Это можно легко сделать, используя string.slice(2)
, чтобы удалить if
.
Если вы чертовски настроены на преобразование своей строки в массив, то тогда это займет немного больше работы, но это легко сделать с помощью лексического анализатора, такого как Lexer. Первое, что вам нужно сделать, это написать несколько правил для различных типов лексем:
var lexer = new Lexer;
lexer.addRule(/\s+/, function() { /* skip whitespace */ });
lexer.addRule(/if\b/g, function() { /* skip the if keyword */ });
// match opening parentheses
lexer.addRule(/\(/, function() { return "("; });
// match closing parentheses
lexer.addRule(/\)/, function() { return ")"; });
// match any other token
lexer.addRule(/[^\s\(\)]+/, function (lexeme) { return lexeme; });
Обратите внимание, что этот лексический ожидает каждый маркер (кроме скобок), чтобы иметь пробелы между ними. Например, $a==10
будет считаться одним токеном, но $a == 10
будет считаться 3 жетонами.
Следующее, что вам нужно, это рудиментарный парсер. Вы можете реализовать один за другим, но было бы больно писать все правила приоритета оператора самостоятельно. Вместо этого я предлагаю использовать следующие parser на основе Dijkstra's shunting yard algorithm.
Теперь мы можем создать парсер следующим образом:
var relational = {
precedence: 3,
associativity: "left"
};
var equality = {
precedence: 2,
associativity: "left"
};
var parser = new Parser({
"<": relational,
"<=": relational,
">": relational,
">=": relational,
"==": equality,
"!=": equality,
"&&": {
precedence: 1,
associativity: "right"
},
"||": {
precedence: 0,
associativity: "right"
}
});
Наконец мы пишем код для подключения лексера анализатору и генерировать нужный результат:
function parse(string) {
lexer.setInput(string);
var tokens = [], token;
while (token = lexer.lex()) tokens.push(token);
tokens = parser.parse(tokens);
var stack = [], length = tokens.length, index = 0;
while (index < length) {
token = tokens[index++];
switch (token) {
case "<":
case "<=":
case ">":
case ">=":
case "==":
case "!=":
case "&&":
case "||":
var b = stack.pop();
var a = stack.pop();
stack.push([a, token, b]);
break;
default:
stack.push(token);
}
}
return stack.length && stack[0];
}
Вот и все. Теперь вы можете разобрать вашу строку в массив следующим образом:
var array = parse("if $a == 10 && ($b == '5' || $c == 'test')");
Чтобы увидеть результат, вы можете использовать JSON.stringify
. Посмотрите демо для себя: http://jsfiddle.net/d2UYZ/3/
Вы хотите что-то вроде: для первого условия возьмите два массива (один для условия и другой для оператора «&&», «||») и добавьте этот массив в список массивов. .. и то же самое делать для других запросов (второй и третий запрос)? Пожалуйста посоветуй. –
Какой ваш вариант использования? Я думаю, что есть более простые альтернативы тому, что вы пытаетесь сделать. –
Я хочу преобразовать оператор if в массив с помощью javascript –