এএনটিএলআর: এর কোনও সাধারণ উদাহরণ আছে কি?


230

আমি এএনটিএলআর দিয়ে শুরু করতে চাই, তবে অ্যান্টলআরর্গ সাইটে উদাহরণগুলি পর্যালোচনা করে কয়েক ঘন্টা ব্যয় করার পরেও আমি জাভা প্রক্রিয়াটির ব্যাকরণ সম্পর্কে পরিষ্কার ধারণা পেতে পারি না।

কিছু সাধারণ উদাহরণ রয়েছে কি, এএনটিএলআর দ্বারা কার্যকর করা ফোর-অপারেশন ক্যালকুলেটর এর মতো কিছু যা পার্সার সংজ্ঞা এবং জাভা উত্স কোডের সমস্ত পথে চলছে?


2
সেই সুনির্দিষ্ট উদাহরণটি অ্যান্টলারের সাইটে টিউটোরিয়াল হিসাবে ব্যবহৃত হয়েছিল, আমি শেষবার যাচাই করেছিলাম।
কোরি পেটোস্কি

1
@ কোরি পেটোসকি: আপনার লিঙ্কটি সরবরাহ করা যাবে?
এলি

আমি সবেমাত্র এএনটিএলআরতে একটি ভিডিও টিউটোরিয়ালের প্রথম অংশগুলি পোস্ট করেছি। Javadude.com/articles/antlr3xtut দেখুন আশা করি আপনি এটি সহায়ক হিসাবে খুঁজে পেয়েছেন!
স্কট স্টানচিল্ড

2
আমিও আপনার অনুসন্ধান ভাগ করে নিই।
পল ড্রাগার

1
এএনটিএলআর 4 এর সেরা উত্তরটি পারারের বই "দ্য ডেফিনিটিভ এএনটিএলআর 4 রেফারেন্স" কিনুন।
james.garriss

উত্তর:


447

দ্রষ্টব্য : এই উত্তরটি এএনটিএলআর 3 এর জন্য ! আপনি যদি কোনও এএনটিএলআর 4 উদাহরণ সন্ধান করছেন, তবে এই প্রশ্নোত্তর এএনটিএলআর 4 ব্যবহার করে কীভাবে একটি সহজ এক্সপ্রেশন পার্সার এবং মূল্যায়নকারী তৈরি করবেন তা প্রদর্শন করে ।


আপনি প্রথমে একটি ব্যাকরণ তৈরি করুন। নীচে একটি ছোট ব্যাকরণ যা আপনি 4 বেসিক গণিত অপারেটরগুলি ব্যবহার করে তৈরি করা হয়েছে তা প্রকাশের মূল্যায়ন করতে ব্যবহার করতে পারেন: +, -, * এবং /। আপনি প্রথম বন্ধনী ব্যবহার করে গোষ্ঠীভুক্তিগুলিও গোষ্ঠীভুক্ত করতে পারেন।

মনে রাখবেন যে এই ব্যাকরণটি কেবলমাত্র একটি প্রাথমিক একটি: এটি অ্যারারি অপারেটরগুলি (বিয়োগ: -1 + 9) বা ডেসিমালগুলি .99 এর (দশমিক সংখ্যা ছাড়া) হ্যান্ডেল করে না, কেবল দুটি ত্রুটিগুলি নাম হিসাবে চিহ্নিত করে। এটি কেবল নিজের উপর কাজ করতে পারে এমন একটি উদাহরণ।

ব্যাকরণ ফাইলের সামগ্রীগুলি এখানে উদাহরণস্বরূপ :

grammar Exp;

/* This will be the entry point of our parser. */
eval
    :    additionExp
    ;

/* Addition and subtraction have the lowest precedence. */
additionExp
    :    multiplyExp 
         ( '+' multiplyExp 
         | '-' multiplyExp
         )* 
    ;

/* Multiplication and division have a higher precedence. */
multiplyExp
    :    atomExp
         ( '*' atomExp 
         | '/' atomExp
         )* 
    ;

/* An expression atom is the smallest part of an expression: a number. Or 
   when we encounter parenthesis, we're making a recursive call back to the
   rule 'additionExp'. As you can see, an 'atomExp' has the highest precedence. */
atomExp
    :    Number
    |    '(' additionExp ')'
    ;

/* A number: can be an integer value, or a decimal value */
Number
    :    ('0'..'9')+ ('.' ('0'..'9')+)?
    ;

/* We're going to ignore all white space characters */
WS  
    :   (' ' | '\t' | '\r'| '\n') {$channel=HIDDEN;}
    ;

(পার্সার বিধিগুলি ছোট হাতের অক্ষর দিয়ে শুরু হয় এবং লেক্সারের বিধিগুলি মূলধনির সাথে শুরু হয়)

ব্যাকরণ তৈরির পরে, আপনি এটি থেকে একটি পার্সার এবং লেক্সার তৈরি করতে চান। এএনটিএলআর জারটি ডাউনলোড করুন এবং আপনার ব্যাকরণ ফাইলের মতো একই ডিরেক্টরিতে এটি সংরক্ষণ করুন।

আপনার শেল / কমান্ড প্রম্পটে নিম্নলিখিত কমান্ডটি প্রয়োগ করুন:

java -cp antlr-3.2.jar org.antlr.Tool Exp.g

এটিতে কোনও ত্রুটি বার্তা তৈরি করা উচিত নয় এবং এক্সপ্লেক্সার.জভা , এক্সপ্রেসার.জভা এবং এক্সপ্রেস টোকেন ফাইলগুলি এখন উত্পন্ন করা উচিত।

এটি সব ঠিকঠাক কাজ করে কিনা তা দেখতে এই পরীক্ষার শ্রেণিটি তৈরি করুন:

import org.antlr.runtime.*;

public class ANTLRDemo {
    public static void main(String[] args) throws Exception {
        ANTLRStringStream in = new ANTLRStringStream("12*(5-6)");
        ExpLexer lexer = new ExpLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        ExpParser parser = new ExpParser(tokens);
        parser.eval();
    }
}

এবং এটি সংকলন:

// *nix/MacOS
javac -cp .:antlr-3.2.jar ANTLRDemo.java

// Windows
javac -cp .;antlr-3.2.jar ANTLRDemo.java

এবং তারপরে এটি চালান:

// *nix/MacOS
java -cp .:antlr-3.2.jar ANTLRDemo

// Windows
java -cp .;antlr-3.2.jar ANTLRDemo

সবকিছু ঠিকঠাক থাকলে কনসোলে কিছুই মুদ্রিত হচ্ছে না। এর অর্থ পার্সার কোনও ত্রুটি খুঁজে পায় নি। আপনি যখন পরিবর্তিত "12*(5-6)"হন "12*(5-6"এবং তারপরে এটি পুনরায় সংকলন এবং চালনা করেন, সেখানে নিম্নলিখিত মুদ্রণ করা উচিত:

line 0:-1 mismatched input '<EOF>' expecting ')'

ঠিক আছে, এখন আমরা ব্যাকরণে কিছুটা জাভা কোড যুক্ত করতে চাই যাতে পার্সারটি আসলে কার্যকর কিছু করে। কোড যুক্ত করা আপনার ব্যাকরণটির ভিতরে কিছু সাধারণ জাভা কোড রেখে দিয়ে {এবং }ভিতরে করা যায়।

তবে প্রথম: ব্যাকরণ ফাইলে সমস্ত পার্সার বিধিগুলির একটি আদিম দ্বৈত মান প্রদান করা উচিত। returns [double value]প্রতিটি নিয়মের পরে যোগ করে আপনি এটি করতে পারেন :

grammar Exp;

eval returns [double value]
    :    additionExp
    ;

additionExp returns [double value]
    :    multiplyExp 
         ( '+' multiplyExp 
         | '-' multiplyExp
         )* 
    ;

// ...

যার সামান্য ব্যাখ্যা প্রয়োজন: প্রতিটি নিয়মের দ্বিগুণ মান প্রত্যাশিত। এখন কোনও কোড ব্লকের অভ্যন্তরীণ থেকে রিটার্ন মান double value(যা সাধারণ জাভা কোড ব্লকের অভ্যন্তরে নেই {...}) সাথে "ইন্টারঅ্যাক্ট" করতে আপনাকে সামনে ডলার সাইন যুক্ত করতে হবে value:

grammar Exp;

/* This will be the entry point of our parser. */
eval returns [double value]                                                  
    :    additionExp { /* plain code block! */ System.out.println("value equals: "+$value); }
    ;

// ...

ব্যাকরণটি এখানে রয়েছে তবে এখন জাভা কোড যুক্ত হয়েছে:

grammar Exp;

eval returns [double value]
    :    exp=additionExp {$value = $exp.value;}
    ;

additionExp returns [double value]
    :    m1=multiplyExp       {$value =  $m1.value;} 
         ( '+' m2=multiplyExp {$value += $m2.value;} 
         | '-' m2=multiplyExp {$value -= $m2.value;}
         )* 
    ;

multiplyExp returns [double value]
    :    a1=atomExp       {$value =  $a1.value;}
         ( '*' a2=atomExp {$value *= $a2.value;} 
         | '/' a2=atomExp {$value /= $a2.value;}
         )* 
    ;

atomExp returns [double value]
    :    n=Number                {$value = Double.parseDouble($n.text);}
    |    '(' exp=additionExp ')' {$value = $exp.value;}
    ;

Number
    :    ('0'..'9')+ ('.' ('0'..'9')+)?
    ;

WS  
    :   (' ' | '\t' | '\r'| '\n') {$channel=HIDDEN;}
    ;

এবং যেহেতু আমাদের evalনিয়ম এখন দ্বিগুণ ফেরতছে তাই আপনার এএনটিএলআরডি ডেমো.জভাটিকে এতে পরিবর্তন করুন:

import org.antlr.runtime.*;

public class ANTLRDemo {
    public static void main(String[] args) throws Exception {
        ANTLRStringStream in = new ANTLRStringStream("12*(5-6)");
        ExpLexer lexer = new ExpLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        ExpParser parser = new ExpParser(tokens);
        System.out.println(parser.eval()); // print the value
    }
}

আবার (পুনরায়) আপনার ব্যাকরণ (1) থেকে একটি নতুন লেক্সার এবং পার্সার উত্পন্ন করুন, সমস্ত ক্লাস (2) সংকলন করুন এবং এএনটিএলআরডেমো (3) চালান:

// *nix/MacOS
java -cp antlr-3.2.jar org.antlr.Tool Exp.g   // 1
javac -cp .:antlr-3.2.jar ANTLRDemo.java      // 2
java -cp .:antlr-3.2.jar ANTLRDemo            // 3

// Windows
java -cp antlr-3.2.jar org.antlr.Tool Exp.g   // 1
javac -cp .;antlr-3.2.jar ANTLRDemo.java      // 2
java -cp .;antlr-3.2.jar ANTLRDemo            // 3

এবং আপনি এখন 12*(5-6)আপনার কনসোলে মুদ্রিত প্রকাশের ফলাফলটি দেখতে পাবেন !

আবার: এটি একটি খুব সংক্ষিপ্ত ব্যাখ্যা। আমি আপনাকে এএনটিএলআর উইকি ব্রাউজ করতে এবং কিছু টিউটোরিয়াল পড়ার জন্য উত্সাহিত করি এবং / অথবা আমি সবেমাত্র পোস্ট করেছি তার সাথে কিছুটা খেলতে পারি।

শুভকামনা!

সম্পাদনা করুন:

এই পোস্টে উপরের উদাহরণটি কীভাবে প্রসারিত করা যায় তা যাতে দেখানো হয় যাতে Map<String, Double>সরবরাহিত অভিব্যক্তিতে ভেরিয়েবল ধারণ করে এমন একটি সরবরাহ করা যায়।

এই কোডটি অ্যান্টলারের বর্তমান সংস্করণ (জুন ২০১৪) এর সাথে কাজ করার জন্য আমার কয়েকটি পরিবর্তন করা দরকার। ANTLRStringStreamপরিণত করা প্রয়োজন ANTLRInputStream, থেকে পরিবর্তন করা প্রয়োজন ফিরে মান parser.eval()থেকে parser.eval().value, এবং আমি অপসারণ করা প্রয়োজন WSশেষে দফা, কারণ অ্যাট্রিবিউট মান যেমন $channelআর lexer কর্মের মধ্যে প্রদর্শিত অনুমতি দেওয়া হয়।


1
এর বাস্তবায়ন কোথায় parser.eval()ঘটে? এটি পরিষ্কার নয় এখানে বা এএনটিএলআর 3 উইকি!

1
@ জারোদ, ভুল, দুঃখিত, আমি আপনাকে সত্যিই বুঝতে পারি না। evalপার্সার বিধি যা প্রত্যাবর্তন করে a double। তাই সেখানে একটি হল eval()পদ্ধতি আপনি একটি একটি দৃষ্টান্ত উপর কল করতে পারেন ExpParser, যেমন আমিও প্রদর্শিত ANTLRDemo.main(...)। একটি লেক্সার / পার্সার তৈরির পরে, কেবল ফাইলটি খুলুন ExpParser.javaএবং আপনি দেখতে পাবেন যে কোনও eval()পদ্ধতিতে ফিরে আসার উপায় রয়েছে double
বার্ট কায়ার্স

@ বার্ট আমি এক সপ্তাহ ধরে এটি নিয়ে গবেষণা করে চলেছি - এটিই প্রথম উদাহরণ যা বাস্তবে বিশদ এবং প্রথমবারের জন্য যথেষ্ট পরিমাণে পূর্ণ ছিল এবং আমার মনে হয় আমি বুঝতে পেরেছি। আমি প্রায় ছেড়ে দিয়েছি। ধন্যবাদ!
ভিনাইল শাহ

13

গ্যাব্রিয়েল টমাসেট্টির এএনটিএলআর মেগা টিউটোরিয়ালটি খুব সহায়ক

এর ব্যাকরণের উদাহরণ রয়েছে, বিভিন্ন ভাষার দর্শকদের উদাহরণ (জাভা, জাভাস্ক্রিপ্ট, সি # এবং পাইথন) এবং আরও অনেক কিছু। অত্যন্ত বাঞ্ছনীয়.

সম্পাদনা: এএনটিএলআরে গ্যাব্রিয়েল টমাসেট্টির অন্যান্য দরকারী নিবন্ধগুলি


দুর্দান্ত টিউটোরিয়াল!
মণীশ প্যাটেল

অ্যান্টলারের এখন সিপিসিও লক্ষ্য ভাষা হিসাবে রয়েছে। সিপিসিতে উদাহরণ সহ কোনও টিউটোরিয়াল আছে কি?
ভিনিশভগুলি

একই লোকটি C ++ tomassetti.me/getting-started-antlr-cpp এএনটিএলআর জন্য একটি টিউটোরিয়াল তৈরি করেছে আমি অনুমান করছি আপনি এখানে যা মেগা টিউটোরিয়ালে যা খুঁজছেন তা আপনি খুঁজে পেতে যাচ্ছেন
একা

7

অ্যান্টালার 4 এর জন্য জাভা কোড জেনারেশন প্রক্রিয়াটি নীচে রয়েছে: -

java -cp antlr-4.5.3-complete.jar org.antlr.v4.Tool Exp.g

সেই অনুযায়ী ক্লাসপথে আপনার জারের নাম আপডেট করুন।


2

https://github.com/BITPlan/com.bitplan.antlr আপনি কিছু কার্যকর সাহায্যকারী শ্রেণীর এবং কয়েক সম্পূর্ণ উদাহরণ সহ একটি ANTLR জাভা লাইব্রেরি খুঁজে পাবেন। এটি মাভেনের সাথে ব্যবহার করতে প্রস্তুত এবং আপনি যদি গ্রহন এবং মাভেন পছন্দ করেন।

https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/main/antlr4/com/bitplan/exp/Exp.g4

একটি সাধারণ এক্সপ্রেশন ভাষা যা গুন করতে এবং ক্রিয়াকলাপ যোগ করতে পারে। https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/test/java/com/bitplan/antlr/TestExpParser.java এর জন্য সংশ্লিষ্ট ইউনিট পরীক্ষা রয়েছে।

https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/main/antlr4/com/bitplan/iri/IRIParser.g4 তিনটি ভাগে বিভক্ত একটি আইআরআই পার্সার:

  1. পার্সার ব্যাকরণ
  2. লেক্সার ব্যাকরণ
  3. আমদানি করা লেক্সবাসিক ব্যাকরণ

https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/test/java/com/bitplan/antlr/TestIRIParser.java এর ইউনিট পরীক্ষা রয়েছে।

ডান পেতে ব্যক্তিগতভাবে আমি এটি সবচেয়ে জটিল অংশটি পেয়েছি। Http://wiki.bitplan.com/index.php/ANTLR_maven_plugin দেখুন

https://github.com/BITPlan/com.bitplan.antlr/tree/master/src/main/antlr4/com/bitplan/expr

পূর্ববর্তী সংস্করণে এএনটিএলআর 4 এর পারফরম্যান্স ইস্যুর জন্য তৈরি করা হয়েছে এমন আরও তিনটি উদাহরণ রয়েছে। এরই মধ্যে এই বিষয়গুলি টেস্টকেস https://github.com/BITPlan/com.bitplan.antlr/blob/master/src/test/java/com/bitplan/antlr/TestIssue994.java শো হিসাবে স্থির করা হয়েছে ।


2

সংস্করণ 4.7.1 কিছুটা আলাদা ছিল: আমদানির জন্য:

import org.antlr.v4.runtime.*;

মূল বিভাগের জন্য - চার স্ট্রিমগুলি নোট করুন:

CharStream in = CharStreams.fromString("12*(5-6)");
ExpLexer lexer = new ExpLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
ExpParser parser = new ExpParser(tokens);
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.