2012-11-29 19 views
7

मैंने एएसटी पेड़ का उपयोग करके एंटर 3 का उपयोग करके एक जटिल व्याकरण विकसित किया है। एएनटीएलआर लेक्सर और पार्सर उत्पन्न करता है। समस्या यह है कि जब उपयोगकर्ता एक वाक्यविन्यास में प्रवेश करता है जो उदाहरण के लिए मान्य नहीं है, तो व्याकरण ';' की अपेक्षा कर रहा है। उपयोगकर्ता मैं निम्नलिखित अपवाद मिल मेरी ग्रहण आईडीई में तो यह प्रवेश नहीं करता,:एंटरल हैंडलिंग अपवाद

line 1:24 mismatched input '<EOF>' expecting ';' 

कैसे इस अपवाद संभाला जा सकता है क्योंकि मैं इस अपवाद को पकड़ने की कोशिश, लेकिन अपवाद catched नहीं है। क्या यह एक अपवाद है? मुझे समझ में नहीं आता कि यह अपवाद क्यों पकड़ा नहीं गया है। मैंने पता लगाने की कोशिश की, हालांकि एंटरल वेबसाइट अब कुछ समय से नीचे प्रतीत होती है।

मैंने निम्न पर देखा: ANTLR exception handling with "$", Java और उस उदाहरण का पालन किया, लेकिन जब लेक्सर RuntimeException() जोड़कर कोड उत्पन्न करता है, तो मुझे पहुंचने योग्य कोड नहीं मिलता है।

मुझे यकीन नहीं है कि क्या करना है।

जब मैं पार्सर यह प्रदर्शित करता है से वाक्यविन्यास त्रुटियों की संख्या प्राप्त करने की कोशिश 0.

संपादित करें:

मैं एक समाधान है कि को देखकर काम करता पाया है: ANTLR not throwing errors on invalid input

हालांकि, जब मैं अपवाद संदेश वापस पाने का प्रयास करता हूं, यह शून्य है। क्या मैंने सब ठीक से सेट किया है? कृपया नमूना व्याकरण देखें:

grammar i; 

options { 
output=AST; 
} 

@header { 
package com.data; 
} 

@rulecatch { 
    catch(RecognitionException e) { 
     throw e; 
    } 
} 

// by having these below it makes no difference 
/**@parser::members { 
    @Override 
    public void reportError(RecognitionException e) { 
     throw new RuntimeException("Exception : " + " " + e.getMessage()); 
    } 
} 

@lexer::members { 
    @Override 
    public void reportError(RecognitionException e) { 
     throw new RuntimeException("Exception : " + " " + e.getMessage()); 
    } 
}*/ 

संपादित करें:

कृपया देखो क्या मैं अब तक है:

grammar i; 

options { 
output=AST; 
} 

@header { 
package com.data; 
} 

@rulecatch { 
    // ANTLR does not generate its normal rule try/catch 
    catch(RecognitionException e) { 
     throw e; 
    } 
} 

@parser::members { 
    @Override 
    public void displayRecognitionError(String[] tokenNames, RecognitionException e) { 
     String hdr = getErrorHeader(e); 
     String msg = getErrorMessage(e, tokenNames); 
     throw new RuntimeException(hdr + ":" + msg); 
    } 
} 

@lexer::members { 
    @Override 
    public void displayRecognitionError(String[] tokenNames, RecognitionException e) { 
     String hdr = getErrorHeader(e); 
     String msg = getErrorMessage(e, tokenNames); 
     throw new RuntimeException(hdr + ":" + msg); 
    } 
} 

operatorLogic : 'AND' | 'OR'; 
value  : STRING; 
query  : (select)*; 
select  : 'SELECT'^ functions 'FROM table' filters?';'; 
operator : '=' | '!=' | '<' | '>' | '<=' | '>='; 
filters : 'WHERE'^ conditions; 
members : STRING operator value; 
conditions : (members (operatorLogic members)*); 
functions : '*'; 
STRING : ('a'..'z'|'A'..'Z')+; 
WS  : (' '|'\t'|'\f'|'\n'|'\r')+ {skip();}; // handle white space between keywords 

public class Processor { 

public Processor() { 

} 

/** 
* This method builds the MQL Parser. 
* @param args the args. 
* @return the built IParser. 
*/ 
private IParser buildMQLParser(String query) { 
    CharStream cs = new ANTLRStringStream(query); 
    // the input needs to be lexed 
    ILexer lexer = new ILexer(cs); 
      CommonTokenStream tokens = new CommonTokenStream(); 
    IParser parser = new IParser(tokens); 
    tokens.setTokenSource(lexer); 
    // use the ASTTreeAdaptor so that the grammar is aware to build tree in AST format 
    parser.setTreeAdaptor((TreeAdaptor) new ASTTreeAdaptor().getASTTreeAdaptor()); 
return parser; 
} 

/** 
* This method parses the MQL query. 
* @param query the query. 
*/ 
public void parseMQL(String query) { 
    IParser parser = buildMQLParser(query); 
    CommonTree commonTree = null; 
    try { 
        commonTree = (CommonTree) parser.query().getTree(); 
        } 
    catch(Exception e) { 
     System.out.println("Exception :" + " " + e.getMessage()); 
    } 
} 
} 

public class ASTTreeAdaptor { 

public ASTTreeAdaptor() { 

} 

/** 
* This method is used to create a TreeAdaptor. 
* @return a treeAdaptor. 
*/ 
public Object getASTTreeAdaptor() { 
    TreeAdaptor treeAdaptor = new CommonTreeAdaptor() { 
     public Object create(Token payload) { 
     return new CommonTree(payload); 
     } 
    }; 
    return treeAdaptor; 
} 
} 

तो जब मैं यह डालें: बिना तालिका

से चुनें * ए ';'

catch(Exception e) { 
    System.out.println("Exception : " + " " e); 
} 

जब मैं कोशिश:

e.getMessage(); 

यह शून्य देता है मैं एक MismatchedTokenException मिलता है।

उत्तर

5

बजाय displayRecognitionError अधिभावी प्रयास करें

@parser::members { 
    ... 
    private YourErrorTrackerInterface errorTracker; 

    //getter/setter for errorTracker here   

    @Override  
    public void displayRecognitionError(String[] tokenNames, RecognitionException e) { 
     String hdr = getErrorHeader(e); 
     String msg = getErrorMessage(e, tokenNames); 
     if (errorTracker != null){ 
      errorTracker.addError(e, tokenNames, hdr, msg); 
     } 
    } 
    ... 
} 
//same code in @lexer::members 

त्रुटि नजर तो तय कर सकता है अपवाद फेंकने या जारी रखने के लिए।


उपरोक्त कोड आपको "पुनर्प्राप्ति योग्य" त्रुटियों को ट्रैक करने की अनुमति देता है, त्रुटियां जो एएनटीएलआर छोड़ सकती हैं। अभी भी ऐसे परिदृश्य हैं जो अप्राप्य त्रुटियों का उत्पादन करते हैं, जैसे कि SELECT * FROM table (; समाप्त होने के बिना)। उस स्थिति में, आपको parseMQL या वहां कहीं भी अपवादों को पकड़ना होगा। (आप अपना खुद का रिकवरी कोड लिखने का प्रयास कर सकते हैं, लेकिन मैं आपको सलाह नहीं दूंगा।)

यहां एक संशोधित parseMQL है जो दो अलग-अलग प्रकार की पार्सिंग त्रुटियों को दिखाता है। ध्यान दें कि मैं getMessage करने के लिए कॉल हटा दिया क्योंकि सभी अपवाद RecognitionException के बंद व्युत्पन्न में भरने

public void parseMQL(String query) { 
    iParser parser = buildMQLParser(query); 
    CommonTree commonTree = null; 
    try { 
     commonTree = (CommonTree) parser.query().getTree(); 
    } catch (MismatchedTokenException e){ 
     //not production-quality code, just forming a useful message 
     String expected = e.expecting == -1 ? "<EOF>" : iParser.tokenNames[e.expecting]; 
     String found = e.getUnexpectedType() == -1 ? "<EOF>" : iParser.tokenNames[e.getUnexpectedType()]; 

     System.out.println("Fatal mismatched token exception: expected " + expected + " but was " + found); 

    } catch (RecognitionException e) { 
     System.out.println("Fatal recognition exception " + e.getClass().getName() 
       + " : " + e); 

    } catch (Exception e) { 
     System.out.println("Other exception : " + e.getMessage()); 
    } 
} 

इनपुट SELECT * FROM table संदेश पैदा करता है "घातक बेमेल टोकन अपवाद:। उम्मीद ';' लेकिन < ईओएफ > था "। यह अपवाद सीधे एएनटीएलआर द्वारा उत्पादित किया गया था।

इनपुट SELECT FROM table; संदेश "अन्य अपवाद: पंक्ति 1: 7: 'तालिका से' गायब '*' उत्पन्न करता है। यह अपवाद ऊपर दिए गए कोड द्वारा उत्पादित किया गया था।

+0

यह या तो काम नहीं करता है। जब मैं संदेश वापस पाने का प्रयास करता हूं, तो मैं सामान्य रूप से वापस वापस आ जाता हूं। – user1646481

+0

कृपया मेरे पास अब जो कुछ है उसके ऊपर संपादित करें देखें। शायद मैं यहाँ कुछ गलत कर रहा हूँ। मैं अपवादों को ट्रैक नहीं करना चाहता हूं लेकिन वास्तव में उन्हें प्रिंट करता हूं। – user1646481

+0

यह सुनिश्चित नहीं करता है कि यह मदद करता है: http://stackoverflow.com/questions/4627244/catching-errors-in-antlr-and-finding-parent – user1646481

1

यदि मैं सही ढंग से समझता हूं तो आप अपनी भाषा वाक्यविन्यास त्रुटियों को संभालना चाहते हैं। इस प्रकार मेरी परियोजना पर यह सेटअप है।

/** 
* Adapter need for ANTL to recognize our custom nodes 
* 
* @author Greg 
*/ 
public class PhantomTreeAdaptor extends CommonTreeAdaptor{ 

    @Override 
    public Object create(Token payload){ 
     return new ASTNode(payload); 
    } 

    @Override 
    public Object dupNode(Object old){ 
     return (old == null) ? null : ((ASTNode) old).dupNode(); 
    } 

    @Override 
    public Object errorNode(TokenStream input, Token start, Token stop, RecognitionException e){ 
     return new ASTErrorNode(input, start, stop, e); 
    } 
} 

यहाँ त्रुटि नोड

/** 
* This is our custom Error node used by the adapter. 
* 
* @author Greg 
*/ 
public class ASTErrorNode extends ASTNode { 

    org.antlr.runtime.tree.CommonErrorNode delegate; 

    public ASTErrorNode(TokenStream input, Token start, Token stop, RecognitionException e) { 

     delegate = new CommonErrorNode(input, start, stop, e); 

    } 

    public boolean isNil() { 
     return delegate.isNil(); 
    } 

    public int getType() { 
     return delegate.getType(); 
    } 

    public String getText() { 
     return delegate.getText(); 
    } 

    public String toString() { 

     return delegate.toString(); 
    } 

} 

है और यह कैसे यह सब एक साथ चिपके जाता है।

final PhantomSQLLexer lex = new PhantomSQLLexer(input); 

     final CommonTokenStream tokens = new CommonTokenStream(lex); 
     final PhantomSQLParser g = new PhantomSQLParser(tokens); 
     g.setTreeAdaptor(new PhantomTreeAdaptor()); 
     final start_rule_return r = g.start_rule(); 
     if (g.getNumberOfSyntaxErrors() == 0) { 
      if (LOGGER.isDebugEnabled()) { 
       LOGGER.debug("tree=" + ((Tree) r.tree).toStringTree()); 
       LOGGER.debug("-------------------------------------------"); 
      } 
      final ASTNode root = r.tree; 
      exec(root);    
     } 
     else { 
      LOGGER.debug("Error parsing input"); 
     } 

हम तो बस फिर हम सेटअप कस्टम ट्री अनुकूलक (PhantomTreeAdaptor) के साथ हमारे पार्सर हमारे lexer और पार्सर बनाया। वहां से हम जांच सकते हैं कि क्या हमारे पास हमारे कस्टम कोड में त्रुटियां हैं।आप उन्हें ट्रैक करने के लिए कोई हैंडलर इंटरफेस बना सकते हैं आप के बजाय त्रुटियों को ट्रैक निरस्त करने के लिए चाहते हैं

@parser::members { 
    ... 

    @Override  
    public void displayRecognitionError(String[] tokenNames, RecognitionException e) { 
     String hdr = getErrorHeader(e); 
     String msg = getErrorMessage(e, tokenNames); 
     throw new RuntimeException(hdr + ":" + msg); 
    } 
    ... 
} 
//same code in @lexer::members 

,:

+0

मैंने एक कस्टम TreeAdaptor भी स्थापित किया है, और पेड़ से डेटा वापस प्राप्त कर सकते हैं। ऊपर दिखाए गए मेरे संपादन के साथ, मैं अपवाद का प्रकार प्राप्त कर सकता हूं, लेकिन संदेश विवरण वापस नहीं। – user1646481

+0

यह उत्तर, समस्या का उत्तर देने के लिए प्रतीत नहीं होता है। निश्चित नहीं है कि मुझे अपवाद वर्ग का नाम मिल सकता है, लेकिन संदेश विवरण वापस पाने में असमर्थ। – user1646481

+0

यदि आप 'एस्टेररोडोड' देखते हैं तो इसमें पहचान पहचान प्रकार/टेक्स्ट/अपवाद के बारे में सारी जानकारी शामिल है – Greg

संबंधित मुद्दे