Приоритет оператора Jison

Я разрабатываю язык с использованием Jison, и проблема, с которой я сталкиваюсь, заключается в приоритете операторов. Я хочу, чтобы операторы сравнения были первыми операторами, которые будут оценены, например, 1 + 2 < 3 - 3 * 4 станет (1+2) < (3 - (3 * 4))

Правила у меня сейчас:

expression
  : expression OP_COMPARISON expression
    { $$ = { type: "Comparison", operator: $2, args: [$1, $3], location: locationFromObject(@$) } }
  | literal
    { $$ = $literal; }
  | NAME
    { $$ = { type: "Variable", variable: $1, location: locationFromObject(@$) }; }
  | field
    { $$ = { type: "Field", field: $field, location: locationFromObject(@$) }; }
  | '(' ':' typename ')' expression
    { $$ = { type: "Cast", cast_type: $typename, expression: $expression, location: locationFromObject(@$) }; }
  | function_call
    { $$ = $function_call; $$.type = "FunctionCall"; }
  | method_call
    { $$ = $method_call; $$.type = "FunctionCall"; }
  | '(' expression ')'
    { $$ = { type: "Grouped", expression: $expression, location: locationFromObject(@$) }; }
  | OP_PREPOSTFIX expression
    { $$ = { type: "Prefix", operator: $1, arg: $expression, location: locationFromObject(@$) }; }
  | expression OP_PREPOSTFIX
      { $$ = { type: "Postfix", operator: $2, arg: $expression, location: locationFromObject(@$) }; }
  | expression OP_ARITHMETIC expression
    {
      if($1.type == "Arithmetic"){
        $$ = $1;
        $$.args.push($3);
        $$.operators.push($2);
        $$.location = locationFromObject(@$);
      }else{
        $$ = { type: "Arithmetic", operators: [$2], args: [$1, $3], location: locationFromObject(@$) };
      }
    }
  | expression OP_LOGICAL expression
    {
      if($1.type == "Logical"){
        $$ = $1;
        $$.args.push($3);
        $$.operators.push($2);
        $$.location = locationFromObject(@$);
      }else{
        $$ = { type: "Logical", operators: [$2], args: [$1, $3], location: locationFromObject(@$) };
      }
    }
  | '!' expression
    { $$ = {type: "LogicalNot", arg: $expression, location: locationFromObject(@$) }; }
  ;

Любая помощь будет принята с благодарностью

1 ответ

Решение

Лучший способ получить приоритет оператора в грамматике без контекста - использовать несколько правил, которые указывают уровни приоритета. Например, с простой арифметикой:

expression : expression PLUS term
           | expression MINUS term
           | term
           ;

term : term MULTIPLY factor
     | term DIVIDE factor
     | factor
     ;

factor : IDENTIFIER
       | CONSTANT
       | LEFT expression RIGHT
       ;

Используя эту иерархию, реализуются правила арифметики BODMAS.

Вы можете сделать нечто похожее с вашей грамматикой: разбить на несколько правил, представляющих различные уровни приоритета.

(См. Стандартный компилятор, пишущий тексты информатики для большего количества деталей)

Другие вопросы по тегам