سؤال

أحاول تحليل قواعد نحوية في ocamlyacc (تشبه إلى حد كبير yacc العادي) والتي تدعم تطبيق الوظائف بدون عوامل تشغيل (كما هو الحال في Ocaml أو Haskell)، والتشكيلة العادية للعوامل الثنائية والأحادية.أحصل على تعارض تقليل/تقليل مع عامل التشغيل '-'، والذي يمكن استخدامه للطرح والنفي.فيما يلي عينة من القواعد النحوية التي أستخدمها:

%token <int> INT
%token <string> ID
%token MINUS

%start expr
%type <expr> expr

%nonassoc INT ID
%left MINUS
%left APPLY

%%

expr: INT
    { ExprInt $1 }
| ID
    { ExprId $1 }
| expr MINUS expr
    { ExprSub($1, $3) }
| MINUS expr
    { ExprNeg $2 }
| expr expr %prec APPLY
    { ExprApply($1, $2) };

تكمن المشكلة في أنه عندما تحصل على تعبير مثل "a - b"، فإن المحلل اللغوي لا يعرف ما إذا كان يجب اختزاله إلى "a (-b)" (نفي b، متبوعًا بالتطبيق) أو "a - b" ( الطرح).تخفيض الطرح صحيح.كيف يمكنني حل الصراع لصالح تلك القاعدة؟

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

المحلول

لسوء الحظ، الإجابة الوحيدة التي يمكنني التوصل إليها هي زيادة تعقيد القواعد.

  1. ينقسم expr داخل simple_expr و expr_with_prefix
  2. السماح فقط simple_expr أو (expr_with_prefix) في تطبيق

تقوم الخطوة الأولى بتحويل تعارض تقليل/تقليل إلى تعارض تحويل/تقليل، ولكن الأقواس تحل ذلك.

ستواجه نفس المشكلة مع "a b c":فعلا a(b(c)) أو (a(b))(c)؟ستحتاج أيضًا إلى الانفصال applied_expression والمطلوب (applied_expression) في القواعد.

أعتقد أن هذا سيفي بالغرض، لكنني لست متأكدًا:

expr := INT
      | parenthesized_expr
      | expr MINUS expr

parenthesized_expr := ( expr )
                    | ( applied_expr )
                    | ( expr_with_prefix )

applied_expr := expr expr

expr_with_prefix := MINUS expr

نصائح أخرى

حسنًا، هذه الإجابة الأبسط هي مجرد تجاهلها والسماح للخيار الافتراضي بتقليل/تقليل الدقة بالتعامل معها - تقليل القاعدة التي تظهر أولاً في القواعد.وفي هذه الحالة، هذا يعني التخفيض expr MINUS expr في تفضيل ل MINUS expr, ، وهو بالضبط ما تريده.بعد رؤية a-b, ، تريد تحليلها على أنها ناقص ثنائي، بدلاً من ناقص أحادي ثم تطبيق.

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