2011-11-07 2 views
7

CoffeeScript 용 Eclipse/Xtext 플러그인을 작성 중입니다. 필자가 직접 렉서 (lexer)를 작성해야 할 필요가 있음을 깨달았습니다. CoffeeScript 파서는 hand-written lexer을 사용하여 들여 쓰기와 문법의 다른 트릭을 처리합니다.문법 파일없이 사용자 정의 Xtext/ANTLR 렉서 작성하기

Xtext는 org.eclipse.xtext.parser.antlr.Lexer을 확장하고 다시 org.antlr.runtime.Lexer까지 확장하는 클래스를 생성합니다. 그래서 나는 그것을 연장 할 것입니다. 두 가지 방법으로 볼 수 있습니다.

  • mTokens()을 덮어 씁니다. 이것은 생성 된 코드에 의해 수행되어 내부 상태를 변경합니다.
  • nextToken() 오버 라이드는 자연스러운 접근 방법이지만 내부 상태를 추적해야합니다.

문법 파일없이 ANTLR에 대한 간단한 렉서 (lexer)조차도 작성하지 못했습니다. 그래서 가장 쉬운 대답은 하나에 대한 포인터 일 것입니다.

Xtext: grammar for language with significant/semantic whitespace에 대한 대답은 기본 입력 스트림의 토큰을 변경하여 들여 쓰기 문제를 처리하는 todotext을 참조합니다. 나는 coffeescript 문법의 다른 속임수를 다루는 것이 어려울 것이기 때문에 그런 식으로 가고 싶지 않습니다.

UPDATE :

내가 내 질문에 부분적으로 Xtext의 특이 그동안 깨달았다.

+0

'ITokenSource' 만 구현하면됩니다. 그러면 'nextToken' 메소드에서해야 할 일을하면됩니다. http://stackoverflow.com/questions/4414166/antlr-parser-with-manual-lexer를 살펴 보았습니까? Definitive Antlr Reference에서 들여 쓰기 (예 : Python) 처리에 대한 예제가 있습니다. – Jimmy

답변

7

내가 한 일은 다음과 같습니다. 작동합니다.

public class MyLexer extends myprj.parser.antlr.internal.InternalMylangLexer { 
    private SomeExternalLexer externalLexer; 

    public Lexer(CharStream in) { 
    super(in); 
    externalLexer = new SomeExternalLexer(in); 
    } 

    @Override 
    public Token nextToken() { 
    Token token = null; 
    ExternalToken extToken = null; 
    try { 
     extToken = externalLexer.nextToken(); 
     if (extToken == null) { 
     token = CommonToken.INVALID_TOKEN; 
     } 
     else { 
     token = mapExternalToken(extToken); 
     } 
    } 
    catch (Exception e) { 
     token = CommonToken.INVALID_TOKEN; 
    } 
    return token; 
    } 

    protected Token mapExternalToken(ExternalToken extToken) { 
    // ... 
    } 
} 

은 그 때 나는 약간 사용자 정의 파서 들어 있습니다

public class BetterParser extends MylangParser { 
    @Override 
    protected TokenSource createLexer(CharStream stream) { 
    MyLexer lexer = new MyLexer(stream); 
    return lexer; 
    } 
} 

가 나는 또한 가지고 내 MylangRuntimeModule.java이 방법

@Override 
public Class<? extends org.eclipse.xtext.parser.IParser> bindIParser() { 
    return myprj.parser.BetterParser.class ; 
} 

을 포함하도록 변경을 그리고 그것 뿐이다. 그런 다음

public class CustomSTLexer extends Lexer { 

    @Override 
    public void mTokens() { 
     // implement lexer here 
    } 
} 

다음과 같이

+0

공유해 주셔서 감사합니다. –

5

(사용자 정의 파서를 만들 필요없이) 또 다른 방법은 Xtext의 렉서 (org.eclipse.xtext.parser.antlr.Lexer)를 확장하여 사용자 정의 렉서를 만드는 것입니다 당신은 당신의 모듈에 바인딩 :

당신이 완전한 예제를 살펴 가지고 싶다면, 내가 StringTemplate에 대한 Xtext 기반 편집기에 대한 사용자 지정 렉서를 구현 한
@Override 
public void configureRuntimeLexer(Binder binder) { 
    binder.bind(Lexer.class) 
       .annotatedWith(Names.named(LexerBindings.RUNTIME)) 
       .to(CustomSTLexer.class); 
} 

hastee을했다.