Haskell のように、通常の中置操作と中置セクションを含む文法の yacc のような実装 (特に ocamlyacc を使用) に問題があります。私はこれらすべてが文法的であることを望みます:
(+1)
(1+)
(+)
(1+1)
ただし、結合性/優先順位の宣言をいじっても、これを機能させることができませんでした。問題が発生している場所は grammar.output で確認できますが (削減したい場所に移動しています)、思い通りに進むように誘導することはできませんでした。これは、問題の単純化されたデモンストレーションです。
lex.mll には次のものがあります。
{
open Parse
exception Eof
}
rule token = parse
| [' ' '\t'] { token lexbuf }
| ['\n'] { EOL }
| ['0'-'9']+ as num {INT(int_of_string num)}
| '+' { PLUS }
| '*' { TIMES }
| '(' { LPAREN }
| ')' { RPAREN }
| eof { raise Eof }
main.ml には次のものがあります。
let _ =
try
let lexbuf = Lexing.from_channel stdin in
while true do
let result = Parse.start Lex.token lexbuf in
print_string result; print_newline(); flush stdout
done
with Lex.Eof -> exit 0
そしてparse.mly(問題があるところ)には次のものがあります:
%token <int> INT
%token PLUS TIMES
%token LPAREN RPAREN
%token EOL
%left PLUS
%left TIMES
%start start
%type <string> start
%%
start:
| expr EOL {$1}
;
expr:
| application {$1}
| expr PLUS expr {"[" ^ $1 ^ "+" ^ $3 ^"]"}
| expr TIMES expr {"[" ^ $1 ^ "*" ^ $3 ^"]"}
;
section:
| LPAREN atom PLUS RPAREN { "(" ^ $2 ^ " +)" }
| LPAREN PLUS atom RPAREN { "(+ " ^ $3 ^ ")" }
| LPAREN PLUS RPAREN { "(+)" }
;
application:
| atom {$1}
| application atom {"[" ^ $1 ^ " " ^ $2 ^ "]"}
;
atom:
| INT {string_of_int $1}
| section { $1 }
| LPAREN expr RPAREN { "(" ^ $2 ^ ")" }
;
%%
それを実行ocamlyacc
すると、 があることがわかります1 shift/reduce conflict
。特に、詳細ログの関連部分は次のとおりです。
Rules:
6 section : LPAREN atom PLUS RPAREN
...
9 application : atom
...
12: shift/reduce conflict (shift 21, reduce 9) on PLUS
state 12
section : LPAREN atom . PLUS RPAREN (6)
application : atom . (9)
PLUS shift 21
INT reduce 9
MINUS reduce 9
TIMES reduce 9
LPAREN reduce 9
RPAREN reduce 9
...
state 21
section : LPAREN atom PLUS . RPAREN (6)
RPAREN shift 26
. error
コンパイルされたプログラムを実行すると、次のすべてが正しく解析されます。
(1+)
(+1)
(+)
1+2
しかし、次のように失敗します:
(1+2)
一方、HIGH
優先度の高いダミー トークンを作成する場合:
%left PLUS MINUS
%left TIMES
%nonassoc HIGH
次に%prec HIGH
、ルール 9 を適用します。
application: atom %prec HIGH {$1}
その場合(1+2)
は解析しますが、し(1+)
ません。
shift/reduce 競合の一般的な背景を理解しています。この解析の課題を解決するために交渉する方法がわかりません。