ANTLR में एक शब्दार्थ विधेय क्या है ?
ANTLR में एक शब्दार्थ विधेय क्या है ?
जवाबों:
ANTLR 4 में विधेय के लिए, इन स्टैक ओवरफ़्लो Q & A की जाँच करें:
एक शब्दार्थ विधेय सादा कोड का उपयोग करके व्याकरण की क्रियाओं पर अतिरिक्त (शब्दार्थ) नियमों को लागू करने का एक तरीका है।
3 प्रकार के शब्दार्थ विधेय हैं:
मान लें कि आपके पास पाठ का एक खंड है, जो केवल कॉमा द्वारा अलग किए गए नंबरों से मिलकर बनता है, जो किसी भी सफेद स्थान को अनदेखा करता है। आप इस इनपुट को यह सुनिश्चित करना चाहते हैं कि संख्याएँ अधिकतम 3 अंकों "लंबी" (अधिकतम 999) पर हों। निम्नलिखित व्याकरण ( 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 मेन
ऐसा करते समय, कंसोल को कुछ भी नहीं मुद्रित किया जाता है, जो इंगित करता है कि कुछ भी गलत नहीं हुआ। बदलने की कोशिश करें:
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
;
बोझिल हो जाती। शब्दार्थ विधेय इस तरह के नियम को सरल बनाने में मदद कर सकता है।
एक मान्य शब्दार्थ विधेय एक प्रश्न चिह्न के बाद कोड के एक ब्लॉक से ज्यादा कुछ नहीं है:
RULE { /* a boolean expression in here */ }?
एक वैध
शब्दार्थ विधेय का उपयोग करके उपरोक्त समस्या को हल करने के लिए , number
व्याकरण में नियम को बदलें :
number
@init { int N = 0; }
: (Digit { N++; } )+ { N <= 10 }?
;
भागों { int N = 0; }
और { N++; }
सादे जावा स्टेटमेंट हैं जिनमें से पहला इनिशियलाइज़ किया गया है जब पार्सर number
नियम में "प्रवेश करता है" । वास्तविक विधेय वह है: { N <= 10 }?
जो किसी FailedPredicateException
भी संख्या को 10 अंकों से अधिक लंबे होने पर पार्सर को फेंकने का कारण बनता है
।
निम्नलिखित का उपयोग करके इसका परीक्षण करें 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");
एक गेटेड अर्थ विधेय एक के समान है मान्य अर्थ विधेय , केवल गेटेड संस्करण एक के बजाय एक सिंटैक्स त्रुटि पैदा करता है 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");
और आप आखिरी बार देखेंगे कि कोई त्रुटि है।
अंतिम प्रकार का विधेय एक अव्यवस्थित अर्थपूर्ण विधेय है , जो एक मान्य विधेय ( {boolean-expression}?
) की तरह थोड़ा सा दिखता है , लेकिन एक gated शब्दार्थ विधेय की तरह अधिक कार्य करता है (कोई अपवाद नहीं फेंका जाता है जब बूलियन अभिव्यक्ति का मूल्यांकन होता है false
)। आप एक नियम की शुरुआत में इसका उपयोग किसी नियम की कुछ संपत्ति की जांच करने के लिए कर सकते हैं और पार्सर मैच को नियम या नहीं कह सकते हैं।
मान लीजिए कि उदाहरण व्याकरण Number
टोकन बनाता है (पार्सर नियम के बजाय एक लेसर नियम) जो 0..999 की सीमा में संख्याओं से मेल खाएगा। अब पार्सर में, आप निम्न और ऊँचाई की संख्या (कम: 0..500, उच्च: 501-999) के बीच अंतर करना चाहेंगे। यह एक अव्यवस्थित अर्थपूर्ण विधेय का उपयोग करके किया जा सकता है जहां आप स्ट्रीम में अगले टोकन का निरीक्षण करते हैं ( 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
input.LT(1)
है getCurrentToken()
अब :-)
मैंने हमेशा अपने गाइड के रूप में wincent.com पर ANTLR के लिए संदर्भ का उपयोग किया है ।