2016-10-06 14 views
0

В компиляторе функционального языка, написанном с использованием счастливого парсера, который очень похож на yacc/bison, я реализовал списки и со списком некоторых основных функций map, concat и filter, используя следующие правила:Как удалить запятые и скобки из вызовов функций

Exp: 
... 
| concat '(' Exp ',' Exp ')'   { Concat $3 $5 } 
| map '(' Exp ',' Exp ')'   { Map $3 $5 } 
| filter '(' Exp ',' Exp ')'   { Filter $3 $5 } 

Это работает просто отлично, но в большинстве функциональных языков нет paranthesis или запятые, поэтому вместо map(myfun, [1,2,3]) я предпочел бы написать map myfun [1,2,3]. Очевидная модификация в грамматике заключается в следующем:

Exp: 
... 
| concat Exp Exp   { Concat $2 $3 } 
| map Exp Exp   { Map $2 $3 } 
| filter Exp Exp   { Filter $2 $3 } 

Но эта модификация включает в себя множество конфликтов уменьшения уменьшения. Как я могу достичь разбора вызовов функций без запятых и paranthesis?

Наименьшее противоречивыми грамматики я мог бы извлечь был такой:

Exp : 
    -- Math 
    Exp '+' Exp       { Op $1 Add $3 } 
    | Exp '-' Exp      { Op $1 Sub $3 } 

    -- Literals 
    | num        { Num $1 } 
    | '-' num %prec NEGATIVE    { Num (-$2) } 

    -- Lists 
    | map Exp Exp      { Map $2 $3 } 

Он генерирует 4 уменьшения/уменьшения конфликтов. Удаление любых правил также приводит к конфликтам. Вот вам full grammar, если вы заинтересованы.

+0

я преобразовал грамматику на GitHub на бизон, и Биссон не сообщал о конфликтах. – rici

+0

@ric, потому что полная грамматика связана с правилами, которые я изложил сначала, а не так, как я действительно хочу (второй пример на копии моего сообщения). – fotanus

+0

: вот почему мы всегда просим [mcve]. – rici

ответ

1

Проблема заключается в том, что, поскольку в приложении приложения нет токена, разрешение конфликта приоритетов на основе токенов работает не очень хорошо - когда он пытается принять решение о сдвиге, который может быть функциональным приложением и уменьшением некоторых другое выражение, токен lookahead - это то, что начинается с выражения аргумента; там нет токена «пробела», который можно использовать.

Чтобы взломать эту проблему и заставить ее работать, вам необходимо установить приоритет знака EVERY, который может быть выражением (каждый токен в FIRST (Exp)), чтобы использовать функцию приложения приложения. Если какой-либо из этих токенов нуждается в каком-либо другом приоритете (например, любой токен, который может быть либо инфиксным, либо префиксным), это становится намного сложнее и может не работать.

Альтернатива, которая могла бы работать лучше, чтобы не использовать правило приоритета на всех - вместо этого, неоднозначности грамматики с различными правилами для каждого уровня приоритета:

Exp: Term | Exp '+' Term 
Term: Factor | Term '*' Factor 
Factor: Primary | Factor Primary 
Primary: num | id | '(' Exp ')'