YACC/Bison ، قلل من المبلغ عن طريق تجميع OPS الرياضيات

StackOverflow https://stackoverflow.com/questions/1410875

  •  05-07-2019
  •  | 
  •  

سؤال

أنا أنظر إلى مصدر حساب هنا http://epaperpress.com/lexandyacc/

أرى خطوط الأطروحات في calc.y

| expr '+' expr         { $$ = opr('+', 2, $1, $3); }
| expr '-' expr         { $$ = opr('-', 2, $1, $3); }
| expr '*' expr         { $$ = opr('*', 2, $1, $3); }
| expr '/' expr         { $$ = opr('/', 2, $1, $3); }
| expr '<' expr         { $$ = opr('<', 2, $1, $3); }
| expr '>' expr         { $$ = opr('>', 2, $1, $3); }

هل هناك طريقة لتجميعهم؟ لذلك يمكنني كتابة شيء مثل أدناه بدلاً من ذلك؟

| expr mathOp expr         { $$ = opr(mathOp, 2, $1, $3); }
| expr cmpOp  expr         { $$ = opr(cmpOp, 2, $1, $3); }

ملاحظة: أنا أستخدم Bison.

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

المحلول

المشكلة في تجميعها هكذا هي أنك تفقد الأوقات على القواعد - ليس لديك سوى قاعدة واحدة لها أسبقية مختلفة اعتمادًا على ما هي الرياضيات ، والتي لا يمكن للبيسون/YACC التعامل معها. ومع ذلك ، يمكنك تجميع OPS من نفس مستوى الأسبقية معًا

expr: expr mulOp expr { $$ = opr($2, 2, $1, $3); } %prec '*'
    | expr addOp expr { $$ = opr($2, 2, $1, $3); } %prec '+'
    | expr relOp expr { $$ = opr($2, 2, $1, $3); } %prec '<'
             :

mulOp: '*' { $$ = '*'; }
     | '/' { $$ = '/'; }
;

نصائح أخرى

يمكنك القيام بذلك بطريقتين:

  • في LEX ، حدد التعرف على المشغلين وتوفير رمز طرفي (في بناء الجملة الخاص بك) مع قيمة المشغل "+" ، "-" ...
  • باستخدام Mathop باعتباره غير الطرفي ، يمكنك إرجاع بعض القيمة المرتبطة بها:

    Mathop: '+' {$$ = '+' ؛ } | '-' {$$ = '-' ؛ } ...

ثم سيبدو الاستخدام (انتبه إلى 2 دولار):

| expr mathOp expr         { $$ = opr($2, 2, $1, $3); }

قد تكون ترغب في تحديد Mathop أكثر تعقيدًا ثم استخدم ٪

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