정규 표현식을 구문 분석하여 유한 상태 자동 완성을 작성하는 재귀 알고리즘을 작성했습니다. 오토마타는 표현식을 반복하여 문자를 스택으로, 연산자를 "연산자 스택"으로 푸시합니다. "("(그룹화 연산을 나타냄)을 만났을 때 스택에 "sub automaton"를 푸시하고 패턴의 나머지 부분을 파싱 할 서브 자동화에 전달합니다.) 해당 오토 마톤이 ")"을 만날 때 나머지 파싱을 끝내기 위해 부모 오토 마톤까지의 문자열. 코드는 다음과 같습니다.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));
}
}
};
"문제가있는 부분"이라고 표시된 부분에주의하십시오. 정규식 "(a | b) a"가 주어지면 this.parent.parse라는 호출은 정확히 한 번 호출됩니다. 즉, 하위 자동 장치가 ")"을 만날 때입니다. 이 시점에서, pattern.substring (i, pattern.length) = ") a". 이것은 "작동"하지만 부모 오토 마톤에 문자열을 전달하기 전에 "") 입력을 사용해야하므로 올바르지 않습니다. 그러나 this.parent.parse에 대한 호출을 변경하면 (pattern.substring (i + 1, pattern.length)) 구문 분석을 통해 빈 문자열이 전달됩니다. 코드를 단계별로 실행했지만이 동작을 설명 할 수 없습니다. 나는 누락 되었습니까?
Juan의 제안에 따라이 알고리즘을 사용하여 "(a | b) a"를 구문 분석하려고 할 때 문제를 보여주기 위해 jsfiddle을 사용했습니다. ")"의 경우 빈 div가 i 인덱스의 하위 문자열과 i + 1 인덱스의 하위 문자열 i에있는 하위 문자열에는 2 개의 문자가 있지만 i + 1에있는 하위 문자열은 빈 문자열입니다. 여기에 링크가 있습니다 : http://jsfiddle.net/XC6QM/1/
EDIT : charAt (i)를 사용하면 알고리즘의 동작이 변경되지 않는다는 사실을 반영하여이 질문을 편집했습니다.
사람들이 게임을 할 수 있도록 http://jsfiddle.net을 만들 수 있습니까? 문제를 시각화하기가 어렵습니다. –
좋은 아이디어입니다. 여기 링크가 있습니다 : http://jsfiddle.net/XC6QM/1/ –
내 대답을보십시오. 문제의 최선의 설명이라고 생각합니다. –