antlr - एएनटीएलआर में 'अर्थपूर्ण भविष्यवाणी' क्या है?




antlr3 antlr4 (2)

एएनटीएलआर 4

एएनटीएलआर 4 में भविष्यवाणी के लिए, इन स्टैक ओवरफ्लो क्यू एंड ए की जांच करें:

एएनटीएलआर 3

एक अर्थपूर्ण भविष्यवाणी सादे कोड का उपयोग करके व्याकरण कार्यों पर अतिरिक्त (अर्थपूर्ण) नियमों को लागू करने का एक तरीका है।

3 प्रकार के अर्थपूर्ण भविष्यवाणी हैं:

  • अर्थपूर्ण भविष्यवाणियों को मान्य करना;
  • गेटेड अर्थशास्त्री भविष्यवाणी करता है;
  • अर्थपूर्ण भविष्यवाणी की असंबद्धता

उदाहरण व्याकरण

आइए मान लें कि आपके पास टेक्स्ट का एक ब्लॉक है जिसमें किसी भी सफेद रिक्त स्थान को अनदेखा करते हुए, अल्पविराम से अलग संख्याओं को शामिल किया गया है। आप यह इनपुट सुनिश्चित करना चाहते हैं कि यह संख्या सुनिश्चित करें कि संख्याएं अधिकतम 3 अंक "लंबी" हैं (अधिकतर 99 9)। निम्नलिखित व्याकरण ( Numbers.g ) ऐसी चीज करेगा:

grammar Numbers;

// entry point of this parser: it parses an input string consisting of at least 
// one number, optionally followed by zero or more comma's and numbers
parse
  :  number (',' number)* EOF
  ;

// matches a number that is between 1 and 3 digits long
number
  :  Digit Digit Digit
  |  Digit Digit
  |  Digit
  ;

// matches a single digit
Digit
  :  '0'..'9'
  ;

// ignore spaces
WhiteSpace
  :  (' ' | '\t' | '\r' | '\n') {skip();}
  ;

परिक्षण

निम्नलिखित वर्ग के साथ व्याकरण का परीक्षण किया जा सकता है:

import org.antlr.runtime.*;

public class Main {
    public static void main(String[] args) throws Exception {
        ANTLRStringStream in = new ANTLRStringStream("123, 456, 7   , 89");
        NumbersLexer lexer = new NumbersLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        NumbersParser parser = new NumbersParser(tokens);
        parser.parse();
    }
}

सभी .java फ़ाइलों को संकलित करने और Main श्रेणी चलाने के लिए लेक्सर और पार्सर उत्पन्न करके इसका परीक्षण करें:

java -cp antlr-3.2.jar org.antlr.Tool Numbers.g
javac -cp antlr-3.2.jar *.java
java -cp .:antlr-3.2.jar Main

ऐसा करने पर, कंसोल पर कुछ भी मुद्रित नहीं होता है, जो इंगित करता है कि कुछ भी गलत नहीं हुआ। बदलने का प्रयास करें:

ANTLRStringStream in = new ANTLRStringStream("123, 456, 7   , 89");

में:

ANTLRStringStream in = new ANTLRStringStream("123, 456, 7777   , 89");

और परीक्षण फिर से करें: आपको स्ट्रिंग 777 ठीक बाद कंसोल पर दिखाई देने वाली त्रुटि दिखाई देगी।

अर्थपूर्ण भविष्यवाणी

यह हमें अर्थपूर्ण भविष्यवाणियों में लाता है। मान लीजिए कि आप 1 और 10 अंकों के बीच संख्याओं को पार्स करना चाहते हैं। एक नियम जैसे:

number
  :  Digit Digit Digit Digit Digit Digit Digit Digit Digit Digit
  |  Digit Digit Digit Digit Digit Digit Digit Digit Digit
     /* ... */
  |  Digit Digit Digit
  |  Digit Digit
  |  Digit
  ;

बोझिल हो जाएगा। अर्थपूर्ण भविष्यवाणियां इस प्रकार के नियम को सरल बनाने में मदद कर सकती हैं।

1. अर्थपूर्ण भविष्यवाणियों को मान्य करना

एक मान्य अर्थपूर्ण भविष्यवाणी कोड के ब्लॉक से अधिक कुछ नहीं है जिसके बाद प्रश्न चिह्न होता है:

RULE { /* a boolean expression in here */ }?

एक मान्य अर्थपूर्ण भविष्यवाणी का उपयोग कर ऊपर की समस्या को हल करने के लिए, व्याकरण में number नियम को इस प्रकार बदलें:

number
@init { int N = 0; }
  :  (Digit { N++; } )+ { N <= 10 }?
  ;

भागों { int N = 0; } { int N = 0; } और { N++; } { N++; } सादे जावा स्टेटमेंट हैं जिनमें से पहला प्रारंभ होता है जब पार्सर number नियम में प्रवेश करता है। वास्तविक भविष्यवाणी है: { N <= 10 }? , जब भी कोई संख्या 10 अंकों से अधिक लंबी होती है तो पार्सर को FailedPredicateException को फेंकने का कारण बनता है।

निम्नलिखित ANTLRStringStream का उपयोग करके इसका परीक्षण करें:

// all equal or less than 10 digits
ANTLRStringStream in = new ANTLRStringStream("1,23,1234567890"); 

जो कोई अपवाद नहीं पैदा करता है, जबकि निम्नलिखित अपवाद को बढ़ाता है:

// '12345678901' is more than 10 digits
ANTLRStringStream in = new ANTLRStringStream("1,23,12345678901");

2. गेटेड अर्थपूर्ण भविष्यवाणी

एक गेटेड अर्थात् भविष्यवाणी एक वैध अर्थात् भविष्यवाणी के समान है, केवल गेटेड संस्करण एक FailedPredicateException बजाय एक वाक्यविन्यास त्रुटि उत्पन्न करता है।

एक गेटेड अर्थात् भविष्यवाणी का वाक्यविन्यास है:

{ /* a boolean expression in here */ }?=> RULE

गेटेड भविष्यवाणियों का उपयोग करके उपर्युक्त समस्या को हल करने के लिए 10 अंकों तक की संख्या से मिलान करने के लिए आप लिखेंगे:

number
@init { int N = 1; }
  :  ( { N <= 10 }?=> Digit { N++; } )+
  ;

दोनों के साथ फिर से परीक्षण करें:

// all equal or less than 10 digits
ANTLRStringStream in = new ANTLRStringStream("1,23,1234567890"); 

तथा:

// '12345678901' is more than 10 digits
ANTLRStringStream in = new ANTLRStringStream("1,23,12345678901");

और आप देखेंगे कि अंतिम बार एक त्रुटि फेंक देगा।

3. अर्थपूर्ण भविष्यवाणियों को असंबद्ध बनाना

भविष्यवाणी का अंतिम प्रकार एक असंबद्ध अर्थपूर्ण भविष्यवाणी है , जो एक मान्य भविष्यवाणी ( {boolean-expression}? ) की तरह थोड़ा दिखता है, लेकिन एक गेटेड अर्थात् भविष्यवाणी की तरह कार्य करता है (जब बुलियन अभिव्यक्ति false मूल्यांकन करती है तो कोई अपवाद नहीं फेंक दिया जाता है)। नियम के कुछ संपत्ति की जांच करने के लिए आप नियम की शुरुआत में इसका उपयोग कर सकते हैं और पार्सर मैच को नियम कहा या नहीं।

आइए मान लें कि उदाहरण व्याकरण Number टोकन बनाता है (एक पार्सर नियम के बजाय एक लेक्सर नियम) जो 0..9 99 की सीमा में संख्याओं से मेल खाता है। अब पार्सर में, आप निम्न और हाइट संख्याओं के बीच एक अंतर बनाना चाहते हैं (कम: 0..500, उच्च: 501..9 99)। यह एक असंबद्ध अर्थपूर्ण भविष्यवाणी का उपयोग करके किया जा सकता है जहां आप स्ट्रीम में अगले टोकन का निरीक्षण करते हैं ( input.LT(1) ) यह जांचने के लिए कि यह कम या उच्च है या नहीं।

एक डेमो:

grammar Numbers;

parse
  :  atom (',' atom)* EOF
  ;

atom
  :  low  {System.out.println("low  = " + $low.text);}
  |  high {System.out.println("high = " + $high.text);}
  ;

low
  :  {Integer.valueOf(input.LT(1).getText()) <= 500}? Number
  ;

high
  :  Number
  ;

Number
  :  Digit Digit Digit
  |  Digit Digit
  |  Digit
  ;

fragment Digit
  :  '0'..'9'
  ;

WhiteSpace
  :  (' ' | '\t' | '\r' | '\n') {skip();}
  ;

यदि अब आप "123, 999, 456, 700, 89, 0" स्ट्रिंग का विश्लेषण करते हैं, तो आपको निम्न आउटपुट दिखाई देगा:

low  = 123
high = 999
low  = 456
high = 700
low  = 89
low  = 0

एएनटीएलआर में अर्थपूर्ण भविष्यवाणी क्या है?


मैंने हमेशा एंटएलआर के टीर्स संदर्भ का उपयोग Wincent.com पर मेरी मार्गदर्शिका के रूप में किया है।