2011-08-26 5 views
4

불완전한 문법을 ​​사용하는 일반적인 방법이 있습니까? 필자의 경우 필자는 단지 델파이 (파스칼) 파일에서 메소드를 감지하고자하는데, 이는 proceduresfunctions을 의미한다. 다음과 같은 첫 번째 시도가 효과적입니다.불완전한 문법으로 파싱하기

methods 
     : (procedure | function | .)+ 
     ; 

전혀 해결책입니까? 더 나은 해결책이 있습니까? 액션 (예를 들어, implementation을 검출 한 후)으로 파싱을 중지 할 수 있습니까? 전 처리기를 사용하는 것이 합리적입니까? 그리고 예 - 어떻게?

grammar PascalFuncProc; 

parse 
    : (Procedure | Function)* EOF 
    ; 

Procedure 
    : 'procedure' Spaces Identifier 
    ; 

Function 
    : 'function' Spaces Identifier 
    ; 

Ignore 
    : (StrLiteral | Comment | .) {skip();} 
    ; 

fragment Spaces  : (' ' | '\t' | '\r' | '\n')+; 
fragment Identifier : ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')*; 
fragment StrLiteral : '\'' ~'\''* '\''; 
fragment Comment : '{' ~'}'* '}'; 

이 트릭을 할 것입니다 :

+0

antlr 등으로는 가능하지 않을지 모르지만, PEG 기반 파서에서는 다소 사소한 것입니다. 단지'(! methods.) +/methods'와 같은 규칙을 정의하면 전체를 구문 분석합니다 스트림으로'메소드'처럼 보이는 모든 것을 탐지합니다. 아마도 여기에서 주석과 문자열 리터럴도 처리하고 싶을 것입니다. –

+0

절차/함수의'Begin'과'End;'사이에 모든 것을 원합니까? 또는 당신은 그 (것)들의 이름에서만 흥미 있는가? –

+0

@ 바트 : 처음에는 이름 만 ... – ANTLRStarter

답변

4

당신은 다음, 이름이 같은 간단한을 찾고 있다면. 필자는 Delhpi/Pascal에 익숙하지 않았기 때문에 StrLiteral 및/또는 Comment을 실행 중입니다.하지만 쉽게 고칠 수 있습니다.

위에서 만 토큰의 두 종류 (Procedure S 및 Function들), 입력의 나머지 (문자열 리터럴 주석 또는 것도 일치하지 않을 경우, 단일 문자 다음 .)을 생성 할 것이다 문법에서 생성 렉서이다 즉시 렉서에서 폐기됩니다 (skip() 방법). 이 같은 입력의

은 :

some valid source 
{ 
    function NotAFunction ... 
} 

procedure Proc 
Begin 
    ... 
End; 

procedure Func 
Begin 
    s = 'function NotAFunction!!!' 
End; 

다음 파스 트리가 생성됩니다 : island grammars

enter image description here

+0

바트, 작품, 흥분하고 실험 중입니다. 다시 감사드립니다 ... – ANTLRStarter

+0

바트는 ANTLR과 함께 즉각적인 문법으로 훌륭합니다. 하지만 ... 문제가 있습니다 (바트의 잘못이 아닙니다). 만약 당신의 langauge가 문자열이나 주석을 허용한다면, 이것은 실수로 **/* procedure Proc is foobarred */**를 프로 시저 선언으로받습니다. 이것은 섬 문법의 문제 중 하나입니다. 귀하의 목적에 맞게 정확해야합니다. 어쩌면 당신은 상관하지 않지만 걱정하지 않거나 당신이 심하게 놀라게 될 것입니다. –

+1

@Ira, err, 필자는 렉서에서 건너 뛸 문자열 리터럴 및 주석 룰을 정의했습니다 ('StrLiteral' 및'Comment' 규칙 참조). 아니면 내가 오해 했습니까? –

3

이라고 당신이에 대해 물어. 개념은 당신이 관심있는 언어 부분 ("섬")을 위해 파서를 정의하고, 그 부분에 필요한 모든 고전적인 토큰 화를 정의하고 나머지 부분은 건너 뛰기 위해 매우 엉성한 파서를 정의한다는 것입니다 ("바다" 섬이 묻혀 있음). 이 작업을 수행하는 한 가지 일반적인 트릭은 엄청난 양의 물건을 집어 넣는 부주의 한 렉서를 정의하는 것입니다 (과거의 HTML을 임베디드 코드로 건너 뛰기 위해 렉서에서 스크립트 태그처럼 보이지 않는 과거는 건너 뛸 수 있습니다. 예).

ANTLR 사이트도 discusses some related issues이지만 특히 ANTLR에 포함 된 예제가 있다고 말합니다. ANTLR에 대한 경험이 없으므로이 특정 정보가 얼마나 유용한 지 알지 못합니다.

구문 분석기를 사용하여 코드를 분석/변환하는 많은 도구를 구축 한 (내 생체 확인) 필자는 섬 문법의 일반적인 유용성에 대해 비관적입니다. 당신의 목적이 파스칼 섬으로 아주 사소한 일을하지 않는다면, 직접 또는 간접적으로 사용하는 모든 식별자의 의미를 수집 할 필요가 있습니다 ... 그리고 대부분은 불행히도 바다에 정의 된 당신을 위해 있습니다. 그래서 IMHO 당신은 꽤 과거의 사소한 일들을 얻기 위해 바다를 파싱해야합니다. 당신은 다른 어려움들도 가질 것이고, 섬의 것들을 정말로 건너 뛰도록 할 것입니다; 이것은 꽤 많이 바다 어휘자가 공백, 주석 및 문자열의 모든 까다로운 구문 (현대 언어로 보이는 것보다 어렵다)을 알게 됨으로써 적절하게 건너 뛸 수 있음을 의미합니다. YMMV.

+0

Ira, 링크 및 답변에 많은 감사드립니다. 정말 귀중한! – ANTLRStarter