سؤال

ما هو المسند الدلالي في Antlr؟

هل كانت مفيدة؟

المحلول

antlr 4

للتنبؤ في antlr 4 ، الخروج هذه كومةالفائض سؤال وجواب:


antlr 3

أ المسند الدلالي هي وسيلة لفرض قواعد إضافية (الدلالية) على الإجراءات النحوية باستخدام رمز عادي.

هناك 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();
    }
}

اختبره عن طريق توليد Lexer و Larser ، وتجميع الجميع .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; } و { N++; } هي عبارات Java العادية التي تتم تهيئة الأولى عندما يدخل المحلل " 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");

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");

وسوف ترى آخر ON سوف يرمي خطأ.


3. إزالة الغموض المتنبئات الدلالية

النوع النهائي من المسند هو الغموض المسند الدلالي, ، والذي يشبه إلى حد ما مسند التحقق ({boolean-expression}?) ، ولكن يتصرف أشبه بالمواد الدلالية ذات البوابات (لا يتم إلقاء أي استثناء عندما يتم تقييم التعبير المنطقي false). يمكنك استخدامه في بداية قاعدة للتحقق من بعض الممتلكات للقاعدة والسماح للمحلل بمباراة القاعدة أو لا.

دعنا نقول أن مثال النحوي يخلقه Number الرموز (قاعدة Lexer بدلاً من قاعدة المحلل) والتي ستتطابق مع الأرقام في حدود 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

نصائح أخرى

لقد استخدمت دائمًا إشارة terse إلى تنبؤات Antlr على wincent.com كدليل.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top