سؤال

أريد أن اجتياز السلسلة الفعلية من الرمز المميز. إذا كان لدي رمز رمزي يسمى، فأنا أريد ملف YACC الخاص بي لمعرفة المعرف بالفعل. أنا لا بد لي من اجتياز سلسلة باستخدام yylval إلى ملف yacc من الملف المرن. كيف يمكنني فعل ذلك؟

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

المحلول

يرى القسم اليدوي المرن على Interfacing مع YACC.

15 تداخل مع YACC

واحدة من الاستخدامات الرئيسية للمرن هي رفيق لجول محلل YACC. يتوقع محلل YACC استدعاء روتين يدعى Yylex () للعثور على رمز الإدخال التالي. من المفترض أن يرجع الروتين نوع الرمز المميز التالي وكذلك وضع أي قيمة مرتبطة في Yylval Global Yylval. لاستخدام Flex مع YACC، يحدد المرء خيار "-d" ل YACC لتعليمه لإنشاء الملف y.tab.h يحتوي على تعريفات لجميع الرموز المئوية التي تظهر في إدخال yacc. ثم يتم تضمين هذا الملف في الماسح الضوئي Flex. على سبيل المثال، إذا كان أحد الرموز المميزة هو tok_number، فقد يبدو جزءا من الماسح الضوئي:

     %{
     #include "y.tab.h"
     %}

     %%

     [0-9]+        yylval = atoi( yytext ); return TOK_NUMBER;

نصائح أخرى

مفتاح إعادة سلسلة أو أي نوع معقد عبر Yylval هو اتحاد Yystype الذي أنشأته yacc في ملف y.tab.h. Yystype هو اتحاد مع عضو لكل نوع من الصفوفين المعرفة ضمن ملف مصدر YACC. على سبيل المثال لإرجاع السلسلة المرتبطة رمز الرمز الرمز المميز في ملف مصدر YACC الذي تعلن عن هذا الاتحاد Yystype باستخدام ٪اتحاد في ملف مصدر yacc:

/*** Yacc's YYSTYPE Union ***/

/* The yacc parser maintains a stack (array) of token values while
   it is parsing.  This union defines all the possible values tokens
   may have.  Yacc creates a typedef of YYSTYPE for this union. All
   token types (see %type declarations below) are taken from
   the field names of this union.  The global variable yylval which lex
   uses to return token values is declared as a YYSTYPE union.
 */

    %union {
        long int4;              /* Constant integer value */
        float fp;               /* Constant floating point value */
        char *str;              /* Ptr to constant string (strings are malloc'd) */
        exprT expr;             /* Expression -  constant or address */
        operatorT *operatorP;   /* Pointer to run-time expression operator */
    };

%type <str> SYMBOL

ثم في ملف مصدر LEX هناك نمط يطابق الرمز الرمز المميز. تقع على عاتق الكود المسؤولية المرتبطة بهذه القاعدة لإرجاع السلسلة الفعلية التي تمثل الرمز. لا يمكنك فقط تمرير مؤشر إلى المخزن المؤقت YYTEXT لأنها مخزن مؤقت ثابت يتم إعادة استخدامه لكل رمز مميز مطابقته. لإرجاع النص المتطابق، يجب نسخ المخزن المؤقت Satic YYTEXT على كومة مع _Strdup () ومؤشر لهذه السلسلة مرت عبر yyval.str. بعد ذلك، فإن قاعدة YACC التي تتطابق مع مسؤولية رمز الرمز عن حرر السلسلة المخصصة لك كومة عندما يتم ذلك.

[A-Za-z_][A-Za-z0-9_]*  {{
    int i;

    /*
    * condition letter followed by zero or more letters
    * digits or underscores
    *      Convert matched text to uppercase
    *      Search keyword table
    *      if found
    *          return <keyword>
    *      endif
    * 
    *      set lexical value string to matched text
    *      return <SYMBOL>
    */

    /*** KEYWORDS and SYMBOLS ***/
    /* Here we match a keywords or SYMBOL as a letter
    * followed by zero or more letters, digits or 
    * underscores.
    */

    /* Convert the matched input text to uppercase */
    _strupr(yytext);         /* Convert to uppercase */

    /* First we search the keyword table */
    for (i = 0; i<NITEMS(keytable); i++) {
        if (strcmp(keytable[i].name, yytext)==0)
            return (keytable[i].token);
    }

    /* Return a SYMBOL since we did not match a keyword */
    yylval.str=_strdup(yytext);
    return (SYMBOL);
}}

إعداد السياق

تحليل بناء الجملة (للتحقق مما إذا كان نص الإدخال يتبع قواعد اللغة المحدد) يتكون من مرحلتين:

  1. قمزة، التي تتم بواسطة أدوات مثل Lex أو Flex، مع واجهة YYLEX ()) و
  2. تحليل دفق الرمز المميز الذي تم إنشاؤه في الخطوة 1 (حسب قواعد اللغة المحددة للمستخدم)، والذي يتم بواسطة أدوات مثل Bison / YACC مع واجهة YYPARESE ()).

وانت تفعل المرحلة 1, ، بالنظر إلى دفق الإدخال، يحدد كل مكالمة إلى yylex () رمز رمزي (سلسلة char) و yytext يشير إلى الحرف الأول من تلك السلسلة. على سبيل المثال: مع دفق الإدخال من "INT X = 10؛" ومع قواعد LEX للأمطيل المطابقة للغة C، فإن أول 5 مكالمات إلى yylex () ستحدد الرموز الثلاثة التالية "int"، "x"، "=" 10 "،"؛ " وفي كل مرة ستشير yytext إلى Char أولا من رمزية العودة.

المرحلة 2., ، المحلل المحلل (الذي ذكرته كما yacc) هو برنامج يدعو وظيفة YYLEX هذه في كل مرة للحصول على رمز مميز ويستخدم هذه الرموز لمعرفة ما إذا كان مطابقا لقواعد قواعد اللغة. ستعود هذه المكالمات إلى Yylex الرموز كرموز عدد صحيح. على سبيل المثال في المثال السابق، قد يرجع أول مكالمات 5 إلى yylex () الأعداد الصحيحة التالية إلى المحلل: اكتب، معرف، EQ_OPERATOR، وعدد صحيح (الذي يتم تعريف قيمها الصحيحة الفعلية في بعض ملف الرأس).

الآن يمكن لجميع المحللين أن نرى هي هذه الرموز الصحيحة، والتي قد لا تكون مفيدة في بعض الأحيان. على سبيل المثال، في المثال قيد التشغيل، قد ترغب في ربط النوع إلى Int، معرف إلى بعض مؤشر جدول الرموز، وعدد صحيح إلى عشري 10. لتسهيل ذلك، يتم إرجاع كل رمز رمزي بواسطة YYLEX مع قيمة أخرى من النوع الافتراضي، ولكن قد يكون لديك أنواع مخصصة لذلك. في بيئة LEX يتم الوصول إلى هذه القيمة مثل Yylval.

على سبيل المثال، مرة أخرى حسب مثال التشغيل، قد يكون Yylex قاعدة التالية لتحديد 10

[0-9]+   {  yylval.intval = atoi(yytext); return INTEGER; }

ومتابعتها لتحديد X

[a-zA-Z][a-zA-Z0-9]*   {yylval.sym_tab_ptr = SYM_TABLE(yytext); return ID;}

لاحظ أنه حددت هنا نوع القيمة (أو Yylval's) كاتحاد يحتوي على INT (INTVAL) ومؤشر INT * (SYM_TAB_PTR).

ولكن في عالم YACC، يتم تحديد هذه القيمة / الوصول إليها ك $ ن. على سبيل المثال، فكر في قاعدة YACC التالية لتحديد بيان تعيين معين

TYPE ID '=' VAL:  { //In this action part of the yacc rule, use $2 to get the symbol table pointer associated with ID, use $4 to get decimal 10.}

الإجابة على سؤالك

إذا كنت ترغب في الوصول إلى قيمة YYTEXT من رمز مميز معين (يرتبط بها Lex World) في YACC World، فاستخدم قيمة الصديق القديم كوحد:

  1. زيادة نوع النقابة من القيمة لإضافة حقل آخر يقول شار * Lex_token_str
  2. في قاعدة Lex، قم بعمل Yylval.lex_token_str = Strdup (YYTEXT)
  3. ثم في YACC World الوصول إليها باستخدام $ n المناسب.
  4. في حال كنت ترغب في الوصول إلى المزيد من قيمة واحدة من الرمز المميز، (على سبيل المثال لمعرف الرمز المميز LEX المحدد، قد يرغب المحلل في الوصول إلى كل من الاسم ومؤشر جدول الرموز)، ثم زيادة نوع النقابة من القيمة مع عضو هيكل، يحتوي على Char * (للاسم) و Int * (لمؤشر Symtab).
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top