سؤال

من البيسون دليل:

في تفاعلية بسيطة الأوامر محلل حيث كل المدخلات سطر واحد ، قد تكون كافية للسماح yyparse إلى العودة 1 على خطأ ويكون المتصل تجاهل بقية سطر الإدخال عندما يحدث ذلك (ثم استدعاء yyparse مرة أخرى).

هذا هو الى حد كبير ما أريد, ولكن أواجه مشكلة في الحصول على العمل.في الأساس أنا أريد الكشف عن خطأ في فليكس ، و إذا تم الكشف عن خطأ ، البيسون تجاهل كامل خط.ما لدي الآن, لا يعمل على حق تماما لأن الأوامر لا يزال الحصول على تنفيذها:

kbsh: ls '/home
Error: Unterminated Single Quote
admin  kbrandt  tempuser
syntax error
kbsh: 

في البيسون الملف:

commands:
     /*Empty*/ { prompt(); } |
     command { prompt(); }
    ;

command:
    error {return 1; } |
    chdir_command |
    pwd_command |
    exit_command |
    WORD arg_list {
        execute_command($1, $2);
        //printf("%s, %s\n", $1, $2); 
    } |
    WORD { execute_command($1, NULL); }
    ;

وفي Flex:

'   {BEGIN inQuote; }

<inQuote>\n {printf("Error: Unterminated Single Quote\n"); BEGIN(0); return(ERROR);}
هل كانت مفيدة؟

المحلول

أنا لا أعتقد أنك سوف تجد الحل بسيط للتعامل مع هذه الأنواع من تحليل الأخطاء في lexer.

أود أن تبقى lexer (فليكس/ليكس) غبي بقدر الإمكان ، يجب أن توفر تيار الأساسية الرموز (معرفات, الكلمات الرئيسية, الخ...) ويكون محلل (yacc/البيسون) القيام اكتشاف الخطأ.في واقع الأمر هو الإعداد على ما تريده بالضبط ، مع القليل من إعادة هيكلة النهج الخاص بك...

في lexer (محلل.l), يبقيه بسيط (لا eol/السطر المناولة) ، شيء من هذا القبيل (لا شيء كامل):

}%

/* I don't recall if the backslashify is required below */
SINGLE_QUOTE_STRING \'.*\'
DOUBLE_QUOTE_STRING \".*\"

%%
{SINGLE_QUOTE_STRING} {
    yylval.charstr = copy_to_tmp_buffer(yytext);  // implies a %union
    return STRING;
}
{DOUBLE_QUOTE_STRING} {
    yylval.charstr = copy_to_tmp_buffer(yytext);  // implies a %union
    return STRING;
}
\n   return NEWLINE;

ثم في محلل.y الملف تفعل كل معالجة حقيقية (لا شيء كامل):

command:
    error NEWLINE
        { yyclearin; yyerrorok; print_the_next_command_prompt(); }
    | chdir_command STRING NEWLINE
        { do_the_chdir($<charstr>2); print_the_next_command_prompt(); }
    | ... and so on ...

هناك نوعان من الأشياء أن نلاحظ هنا:

  1. التحول من الأشياء مثل السطر إلى yacc الجانب بحيث يمكنك تحديد عندما يكون المستخدم القيام به مع الأمر ثم يمكنك مسح الأمور والبدء من جديد (على افتراض لديك "int yywrap() {return 1;}"في مكان ما).إذا كنت في محاولة الكشف عن ذلك في وقت مبكر جدا في فليكس, عندما تعرف أن رفع الخطأ ؟
  2. تشدر ليس أمر واحد (إلا إذا كان دون حكم و لم تظهر عليه) ، لديها الآن chdir_command سلسلة (الحجة إلى تشدر).هذا يجعل من ذلك أن المحلل يمكن معرفة ما حدث من خطأ ، ثم يمكنك yyerror إذا كان هذا الدليل غير موجود ، الخ...

هذه الطريقة يجب أن تحصل على شيء مثل (التخمين ما تشدر قد تبدو):

cd 'some_directory
خطأ في بناء الجملة
cd 'some_directory'
كنت في some_directory يا صاح!

ويتم التعامل معها من قبل yacc نحوي وليس tokenizer.

لقد وجدت أن الحفاظ على فليكس بسيطة بقدر الإمكان يعطي لك أكثر ***فليكس***ibility.:)

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