Как определить ассоциацию по правилу без токенов?
У меня есть следующая минимизированная грамматика
Exp : let var '=' Exp in Exp end { App (Fn $2 $6) $4 }
| Exp Exp { App $1 $2 }
| Exp OpCode Exp { Op $1 Add $3 }
| '(' Exp ')' { $2 }
| num { Num $1 }
| var { Ident $1 }
| '\\' var '.' Exp { Fn $2 $4 }
Exp Exp
Правило используется для применения функции в значении. Но если у меня есть что-то вроде myFunc 1 2
по умолчанию это приоритет myFunc (1 2)
что не то, что я хочу. я хочу (myFunc 1) 2
для карри.
Но как я могу определить ассоциацию, если у меня нет нетерминального символа? Пытаюсь сделать %left Exp
кажется, не помогает
1 ответ
Вы не можете реально применять приоритет или ассоциативность, если у вас нет терминала для сдвига, потому что правила приоритета и ассоциативности используются для разрешения конфликтов сдвига / уменьшения. Вам не обязательно нужен терминал в сокращении, поэтому вы можете использовать поддельный терминал и написать:
Exp: Exp Exp %prec CURRY
Но это не поможет вам, потому что нет терминала для сравнения приоритетов. Отношения приоритета - это всегда сравнение приоритета символа предпросмотра (терминала) и возможных сокращений (по умолчанию приоритет сокращения основан на самом правом терминале в правиле, но, как указано выше, вы можете явно указать).
Поскольку вы не можете сделать это коротким путем, вам нужно вернуться к старомодному стилю, где вы пишете однозначную грамматику с явными правилами приоритета:
Curry: Term
| Curry Term
(Это лево-ассоциативно, на выезде. Если func 1 2
анализируется как ((func 1) 2)
, то приложение связывается слева.)
Предполагая, что инфикс связывает более крепко, чем приложение, вы должны иметь:
Term: Value
| Term Opcode Value
Value: '(' Exp ')'
| num
| var
Exp: Curry
(Вам придется выяснить, как интегрировать лямбды в это. Это зависит от того, как вы ожидаете, что они сгруппируются, но, надеюсь, приведенная выше модель понятна.)