Я пишу рекурсивный алгоритм для построения автомата конечного состояния путем разбора регулярного выражения. Автомат выполняет итерацию через выражение, выталкивая символы в стек и операторы в «стек оператора». Когда я сталкиваюсь с «(» (указывая операцию группировки), я нажимаю «вспомогательный автомат» в стек и передаю остальную часть шаблона на вспомогательный автомат для разбора. Когда этот автомат встречает «)», он передает остальную часть строка до родительского автомата, чтобы закончить синтаксический анализ. Вот код:Явная проблема с поведением подстроки в JavaScript
var NFA = function(par) {
this.stack = [];
this.op_stack = [];
this.parent = par;
};
NFA.prototype.parse = function(pattern) {
var done = false;
for(var i in pattern) {
if (done === true) {
break;
}
switch(pattern.charAt(i)) {
case "(":
var sub_nfa = new NFA(this);
this.stack.push(sub_nfa);
sub_nfa.parse(pattern.substring(i+1, pattern.length));
done = true;
break;
case ")":
if (this.parent !== null) {
var len = pattern.length;
/*TROUBLE SPOT*/
this.parent.parse(pattern.substring(i, pattern.length));
done = true;
break;
}
case "*":
this.op_stack.push(operator.KLEENE);
break;
case "|":
this.op_stack.push(operator.UNION);
break;
default:
if(this.stack.length > 0) {
//only push concat after we see at least one symbol
this.op_stack.push(operator.CONCAT);
}
this.stack.push(pattern.charAt(i));
}
}
};
Обратите внимание на область с надписью «TROUBLE SPOT». Учитывая регулярное выражение «(a | b) a», вызов this.parent.parse вызывается ровно один раз: когда подавтомат встречает «)». На этом этапе pattern.substring (i, pattern.length) = ") a". Это «работает», но это неверно, потому что мне нужно использовать «)», прежде чем передать строку в родительский автомат. Однако, если я изменяю вызов this.parent.parse (pattern.substring (i + 1, pattern.length), синтаксический анализ получает пустую строку! Я попытался пройти через код, и я не могу объяснить это поведение. Я пропустил?
По предложению Хуана я сделал быстрый jsfiddle, чтобы показать проблему при попытке разобрать «(a | b)» с помощью этого алгоритма. В случае «)» он заполняет пустой div с помощью подстроку в индексе i и подстроку в индексе i + 1. Он показывает, что, хотя в подстроке в i есть 2 символа, подстрока в i + 1 является пустой строкой! Вот ссылка: http://jsfiddle.net/XC6QM/1/
EDIT: Я отредактировал этот вопрос, чтобы отразить тот факт, что использование charAt (i) не изменяет поведения алгоритма.
Можете ли вы создать http://jsfiddle.net для людей, с которыми можно играть? Трудно представить себе проблему –
Хорошая идея, вот ссылка: http://jsfiddle.net/XC6QM/1/ –
См. Мой ответ. Я думаю, что это лучшее объяснение вашей проблемы. –