2011-05-16 9 views
3

두 JavaScript 함수의 정적 분석을 사용하여 두 함수가 같은지 확인하는 방법을 찾고 있습니다. "같은"여러 정의를 정의하겠습니다.정적 파싱 : 두 개의 자바 스크립트 함수가 같은지 확인하십시오.

레벨 1 : 가능한 다른 공백을 제외하고는 기능이 동일합니다. TABS, CR, LF 및 SPACE.

레벨 2 레벨 1과 같이 함수의 공백이 다를 수 있지만 변수 이름이 다를 수 있습니다.

레벨 3 ??? 레벨 1의 경우


, 난 그냥 문자열을 비교 한 후 두 JS 함수 정의를 포함하는 각 문자열에서 모든 (힘든 일 수있는, 비 문자)의 공백을 제거하고 수 있다고 생각.

레벨 2의 경우 두 개의 구문 분석 트리를 생성하려면 SpiderMonkey's parser과 같은 것을 사용해야하며 트리를 탐색하고 변수가 다른 이름을 가질 수 있도록 비교자를 작성해야한다고 생각합니다.


[편집] Williham, 아래 좋은 지적입니다. 나는 똑같은 뜻이야. 이제는 파스 트리 사용과 관련하여 실용적인 전략을 찾고 있습니다.

+0

레벨 1의 경우 스키마가 항상 작동하지 않습니다. 예를 들어, 0011은 00011과 "동일"하지만 공백 정규화는이를 인식하지 못합니다. 마찬가지로 같은 값의 다른 모든 철자법은 문자, 숫자 또는 문자열입니다. 자바 스크립트의 경우 "선택적"세미콜론에 대해서도 걱정할 필요가 있습니다. –

답변

3

은 재 편집 :

동일한 기능을 결정하기위한 나의 제안에 상세히 설명하기 위해, 다음과 같은 흐름을 제시 할 수 있습니다

레벨 1 : 리터럴 문자열의 일부가 아닌 공백을 제거; 각 {, ;} 다음에 개행을 삽입하고 비교하십시오. 동등한 경우; 함수가 동일하지 않은 경우 :

레벨 2 : 동일한 범위에 정의 된 다른 변수의 상태에 의존하지 않는 모든 변수 선언 및 할당을 선언 된 범위의 시작으로 이동합니다 (또는 실제로 JS를 파싱하고 싶지는 않지만 중괄호의 시작). 선 길이에 따라 순서를 정하십시오. 모든 변수 이름을 4 자 길이로 취급하고 묶인 길이의 경우 변수 이름을 무시하고 알파벳 순서로 되돌아갑니다. 알파벳순으로 모든 콜렉션을 재정렬하고 모든 변수의 이름을 vSNN으로 바꿉니다. 여기서 v는 리터럴이고 S는 중첩 된 중괄호의 수이며 NN은 변수가 발생한 순서입니다.

개 비교; 동일한 경우, 기능은 동일합니다, 그렇지 않은 경우 :

레벨 3 : "s 리터럴입니다 "sNN", 모든 문자열 리터럴을 교체하고 NN 문자열이 발견 된 순서입니다. 비교; 동등한 경우 함수는 동일합니다.

레벨 4 : 알파벳 순서에 따라 우선 순위가 가장 높은 함수의 이름을 사용하여 동일한 것으로 알려진 함수의 이름을 정규화합니다 (아래 예제에서, p_strlen() 어떤 통화가 c_strlen()로 대체 될 1 급 필요에 따라 재 순서화를 반복 비교;.. 동일한 경우에는 기능하지 않을 경우, 동일한 상기 기능은 거의 확실하게 동일하지


. 원문 답변 :

"동일"이 아니라 "동일"하다는 것을 알게 될 것입니다.

의 차이, 당신은 찾을 수 있습니다으로 중요하다 :

두 기능은 동일 경우, 정상화의 몇 가지 방법으로, (비 문자 공백을 제거 표준화 된 순서로 이름을 변경하고 재 배열 변수를 다음, 문자열 리터럴을 자리 표시 자로 바꾸면 ...) 문자 그대로 같음과 비교됩니다.

두 개의 함수는 동일한 입력 값에 대해 호출 될 때 동일한 반환 값을 제공 할 경우과 같음. 두 개의 함수는 입니다. 일반적인 경우, 카운트 된 프로그래밍 언어, 제로 종료 문자열 (하이브리드 파스칼/C 문자열)을 고려하십시오. p_strlen(str) 함수는 문자열의 문자 수를보고이를 반환 할 수 있습니다. c_strlen(str) 함수는 문자열의 문자 수를 계산하여 반환 할 수 있습니다.

이러한 기능은 분명 동일하지는 않지만 동일합니다. 주어진 (유효한) 입력 값의 경우 동일한 값을 부여합니다.


내 요점은 다음 두 가지 기능이 어떠했는지를 결정

(당신이 달성하고자하는 것하는) 당신이 설명하는대로 수행하는 (적당히) 사소한 문제가 동일합니다.

2 가지 기능을 결정하는 것은 실제로 동일합니다 (실제로 달성하기를 원하는 것)는 중요하지 않습니다. 실제로, 확실한 의미는 Halting Problem과 관련이 있으며 정적 분석으로 수행 할 수있는 작업이 아닙니다.


편집 : 물론, 동일 기능도 동일합니다; 완전한 분석을 위해 매우 구체적이고 거의 유용한 방법은 아닙니다.

1

레벨 1에 대한 접근 방식은 합리적인 것처럼 보입니다.

레벨 2의 경우 각 기능에 대한 초보적인 변수 치환을 수행 한 다음 레벨 1에 대해 승인합니까? 시작 부분에서 시작하여 각 변수 선언의 이름을 var1, var2, ... varX으로 바꿉니다.

다른 명령 ... var ivar j의 변수가 두 함수에서 같은 방식으로 사용될 수 있지만 다른 순서로 선언 된 경우 함수가 도움이되지 않습니다. 그렇다면 아마도 당신이 언급 한 것처럼 파스 트리를 비교할 수 있습니다.

1

내 회사 (시맨틱 디자인) Smart Differencer 도구를 참조하십시오. 이 도구 군은 관심있는 언어 (귀하의 경우 JavaScript)에 대한 컴파일러 수준의 세부 문법에 따라 소스 코드를 구문 분석하고 AST를 작성한 다음 공백과 주석을 효과적으로 무시하는 AST를 비교합니다. 리터럴 값은 정규화되었으므로 "철자"가 어떻게 적용되는지는 중요하지 않습니다. 10E17은 1E18과 동일한 정규화 값을가집니다.

두 나무가 같은 경우 "차이가 없음"을 알립니다. 그들이 식별자의 일관된 이름 변경에 따라 다르다면, 도구는 일관된 이름 바꾸기와 그것이 나타나는 블록을 알려줍니다. 다른 차이점은 언어 요소 (식별자, 문, 블록, 클래스, ...) 삽입, 삭제, 복사 또는 이동으로보고됩니다. 목표는 그 차이를 그럴듯하게 설명하는 작은 델타 세트를보고하는 것입니다. 웹 사이트에서 여러 언어에 대한 예제를 볼 수 있습니다.

실제로이 점을 훨씬 뛰어 넘을 수는 없습니다. 두 함수가 같은 대답을 계산하는지 확인하려면 원칙적으로 중단 문제를 해결해야합니다. 교환 가능 목록의 요소 인 두 언어 요소가 어디에 영향을 미치지 않을 지 감지 할 수 있습니다. 우리는이 작업을하고 있습니다. 정규화 된 다시 쓰기를 적용하여 특정 양식을 표준화 할 수 있습니다 (예 : 여러 개의 선언을 모두 어휘별로 정렬 된 단일 선언으로 매핑). 소스 코드를 동등한 데이터 흐름 집합으로 변환하고 그래프 동형 매치를 수행 할 수 있습니다 (1980 년대 MIT에서 프로그래머의 견습생이 제안했지만, 생각하지는 않습니다).

예상보다 많은 작업이 있습니다.

관련 문제