একটি কি শব্দার্থিক সম্পৃক্ত ANTLR মধ্যে?
একটি কি শব্দার্থিক সম্পৃক্ত ANTLR মধ্যে?
উত্তর:
এএনটিএলআর 4 এ পূর্বাভাসের জন্য, এই স্ট্যাকের ওভারফ্লো প্রশ্নোত্তর ও চেক আউট :
প্লেইন কোড ব্যবহার করে ব্যাকরণ ক্রিয়াকলাপগুলির উপর অতিরিক্ত (শব্দার্থবিজ্ঞান) বিধি প্রয়োগ করার একটি অর্থ হল সিনেমিক প্রিডিকেট ।
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 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
;
জটিল হয়ে উঠবে। শব্দার্থবিজ্ঞান পূর্বাভাসগুলি এই ধরণের নিয়মকে সহজতর করতে সহায়তা করতে পারে।
একটি বৈধতাযুক্ত সিনেমিক প্রিডিকেট একটি প্রশ্ন চিহ্নের পরে কোডের ব্লক ছাড়া আর কিছুই নয়:
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}?
) এর মতো দেখায় , তবে এটি আরও উত্সাহযুক্ত সিনমেটিক প্রাকটিকের মতো কাজ করে (বুলিয়ান এক্সপ্রেশনটি মূল্যায়ন করলে কোনও ব্যতিক্রম ছোঁড়া হয় না 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()
এখন :-)
আমি সর্বদা এএনটিএলআর এর সংক্ষিপ্ত রেফারেন্সটি আমার গাইড হিসাবে উইনসেন্ট.কম এ পূর্বাভাস ব্যবহার করেছি ।