2016-03-24 6 views
1

Итак, у меня есть эта грамматика для языка, грамматика, безусловно, содержит некоторую двусмысленность, однако мне кажется, что это необычно сложно исправить. Ниже приведена грамматика BNF языка и ниже этой части моего файла счастливого парсера.Неоднозначная грамматика и возможные исправления

BNF предлагаемого языка:

<program> ::=         Skel program 
     "program" <id> ":" <pars> "." 

--> <pars> ::= 
     <par> [";" <pars>]      parallel statements 

<par> ::= 
    "func" <id> <structs>      structured expression 
--> | <pars> "||" <pars>       parallel pipeline 
| "farm" <int> <pars>       task farm 

--> <structs> ::= 
    <struct> [";" <structs>]     statements 

<struct> ::= 
     <exprs>         expression 
--> |  <structs> "•" <structs>     composition 
|  "iter" <int> <structs>     iteration 

--> <exprs> ::= 
     <expr> ["," <exprs>]      expressions 

<expr> ::= 
    <int>          integer value 
    | <string>         string value 
    | <bool>         boolean value 
    | <id> [ "=" <exprs> ]      identifier/assignment 
    | "raise" <id> "=" <exprs>     raise exception 
    | <exprs> "catch" <id> <id> ":" <exprs> catch exception 
    | <exprs> <op> <exprs>      binary operator 
    | "(" <exprs> ")"       grouping 

<op> ::=      operators 
    "+" | "*" | "-" | "div"| "<"| "<=" | "==" | "!=" 

Parser.y

TProgram: program ID ':' TPars '.' { Program $2 $4 } 

TPars : TPar ';'     { [$1] } 
     | TPars TPar     { $2 : $1 } 

TPar : func ID TStructs   { Function $2 $3 } 
     --| "||" TPars     { Parall $2  } 
     | farm DIGIT TPars   { Farm $2 $3  } 

TStructs: TStruct ';'     { [$1] } 
     | TStructs TStruct   { $2 : $1 } 

TStruct : TExprs      { ExprList $1 } 
     --| '•' TStructs    { CompOp $2  } 
     | iter DIGIT TStructs   { Iter $2 $3 } 

TExprs : TExpr      { [$1] } 
     | TExprs ',' TExpr   { $3 : $1 } 

BinExpr : Term      { $1 } 
     | BinExpr Op BinExpr   { BinOp $2 $1 $3 } 

Op  : '/'       { Divide } 
     | '*'       { Times } 
     | '-'       { Minus } 
     | '+'       { Plus } 

Term : ID       { Var $1 } 
     | DIGIT      { Digit $1 } 
     | FLOAT      { Float $1 } 

TExpr : '(' TExprs ')'    { ParenExpr $2 } 
     | true      { Bool $1 } 
     | false      { Bool $1 } 
     | ID '=' TExprs    { Assign $1 $3 } 
     | raise ID '=' TExprs   { Raise $2 $4 } 
     | BinExpr      { $1 } 

Edit: Я добавил стрелки в формате BNF, показывающие, что я считаю, что вызывает неоднозначность в грамматике.

+0

Это загадка? Почему бы вам не показать нам двусмысленности? Однако я считаю, что 'a = b, c' может быть проанализирован как' (a = b), c', а также 'a = (b, c)' – Ingo

+0

@ Если это не головоломка, я отметю, что я напомню теперь. – ymg

ответ

3

Итак, как вы хотите

a = true, false 

получить разобран? Это может быть

(a=true), false 

или

a = (true, false) 

Если бы это было Yacc, я хотел бы предложить, чтобы разрешить конфликт, давая «=» и «» ассоциативность и приоритет с %right%left и %nonassoc прагмах, возможно, Happy поддерживает что-то подобное.

+0

Я понимаю, что вы имеете в виду, никогда не думал о том, что вы упомянули (фокусировался на других, таких как последовательности «Парс» и «Структуры»), и да, действительно, Happy поддерживает прагмы, подобные тем, о которых вы упоминали. Спасибо за вашу помощь. – ymg

+0

@ymg Насколько я вижу, существует аналогичная проблема с 'pars' и' structs', в основном у вас есть список вещей, но вещь может закончиться другим списком вещей, поэтому никогда не бывает ясно, где и где внешний список должен заканчиваться. – Ingo

+0

спасибо, ты очень помог! Я только что заметил несколько замечаний после ваших замечаний. – ymg