2011-11-07 32 views
7

Tôi đang viết một trình cắm thêm Eclipse/Xtext cho CoffeeScript và tôi nhận ra rằng có lẽ tôi sẽ cần viết một từ vựng cho nó bằng tay. Trình phân tích cú pháp CoffeeScript cũng sử dụng một số hand-written lexer để xử lý thụt lề và các thủ thuật khác trong ngữ pháp.Viết lexer Xtext/ANTLR tùy chỉnh mà không cần tệp ngữ pháp

Xtext tạo lớp mở rộng org.eclipse.xtext.parser.antlr.Lexer để mở rộng org.antlr.runtime.Lexer. Vì vậy, tôi cho rằng tôi sẽ mở rộng nó. Tôi có thể thấy hai cách để làm điều đó

  • Ghi đè mTokens(). Điều này được thực hiện bởi mã được tạo ra, thay đổi trạng thái bên trong.
  • Ghi đè nextToken() dường như là cách tiếp cận tự nhiên, nhưng sau đó tôi sẽ phải theo dõi trạng thái nội bộ.

Tôi không thể tìm thấy bất kỳ ví dụ nào về cách viết ngay cả một lexer đơn giản cho ANTLR mà không có tệp ngữ pháp. Vì vậy, câu trả lời dễ nhất sẽ là một con trỏ đến một.

Câu trả lời cho Xtext: grammar for language with significant/semantic whitespace đề cập đến todotext xử lý vấn đề thụt đầu dòng bằng cách thay đổi mã thông báo trong luồng đầu vào cơ bản. Tôi không muốn đi theo cách đó, bởi vì sẽ rất khó để xử lý các thủ đoạn khác của ngữ pháp coffeescript.

UPDATE:

tôi nhận ra rằng trong khi chờ đợi câu hỏi của tôi là một phần Xtext cụ thể.

+0

Bạn chỉ cần triển khai 'ITokenSource' - và làm bất cứ điều gì bạn cần làm trong phương thức' nextToken'. Bạn đã kiểm tra http://stackoverflow.com/questions/4414166/antlr-parser-with-manual-lexer Có những ví dụ về xử lý thụt lề (ví dụ trong Python) trong Tham chiếu Antlr Definitive. – Jimmy

Trả lời

7

Đây là những gì tôi đã làm - và nó hoạt động.

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) { 
    // ... 
    } 
} 

Sau đó, tôi có một phân tích cú pháp hơi tùy chỉnh bao gồm:

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

Tôi cũng đã phải thay đổi MylangRuntimeModule.java tôi để chứa phương pháp này

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

Và đó là nó.

+0

Tuyệt vời, cảm ơn bạn đã chia sẻ. –

5

Một cách khác (mà không cần phải tạo ra một phân tích cú pháp tùy chỉnh) là để tạo ra một lexer tùy chỉnh bằng cách mở rộng lexer Xtext của (org.eclipse.xtext.parser.antlr.Lexer) như sau:

public class CustomSTLexer extends Lexer { 

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

Sau đó, bạn gắn nó trong module của bạn:

@Override 
public void configureRuntimeLexer(Binder binder) { 
    binder.bind(Lexer.class) 
       .annotatedWith(Names.named(LexerBindings.RUNTIME)) 
       .to(CustomSTLexer.class); 
} 

Nếu bạn muốn có một cái nhìn tại một ví dụ hoàn chỉnh, tôi đã thực hiện một lexer tùy chỉnh cho một biên tập viên Xtext có trụ sở tại StringTemplate gọi hastee.

Các vấn đề liên quan