2017-09-29 7 views
1

私は単純なプログラムを解析する方法を学ぶ途中です。ocaml menhirパーサーの生産量が減ることはありません

これは私のレクサーです。

{ 
open Parser 
    exception SyntaxError of string 
} 

let white = [' ' '\t']+ 

let blank = ' ' 


let identifier = ['a'-'z'] 


rule token = parse 
    | white {token lexbuf} (* skip whitespace *) 
    | '-' { HYPHEN } 
    | identifier { 
    let buf = Buffer.create 64 in 
    Buffer.add_string buf (Lexing.lexeme lexbuf); 
    scan_string buf lexbuf; 
    let content = (Buffer.contents buf) in 
    STRING(content) 
    } 
    | _ { raise (SyntaxError "Unknown stuff here") } 

and scan_string buf = parse 
    | ['a'-'z']+ { 
    Buffer.add_string buf (Lexing.lexeme lexbuf); 
    scan_string buf lexbuf 
    } 
    | eof {() } 

マイ "AST":

type t = 
    String of string 
    | Array of t list 

マイパーサ:

%token <string> STRING 
%token HYPHEN 

%start <Ast.t> yaml 
%% 

yaml: 
    | scalar { $1 } 
    | sequence {$1} 
    ; 

sequence: 
    | sequence_items { 
    Ast.Array (List.rev $1) 
    } 
    ; 

sequence_items: 
    (* empty *) { [] } 
    | sequence_items HYPHEN scalar { 
    $3::$1 

    }; 

scalar: 
    | STRING { Ast.String $1 } 
    ; 

私は無地の '文字列' を解析するためにどちらかたいポイントで、現在よ、すなわち some textまたは '文字列'の '配列'、つまり- item1 - item2です。私は立石とパーサをコンパイルすると

は私が取得:

Warning: production sequence -> sequence_items is never reduced. 
Warning: in total, 1 productions are never reduced. 

私は構文解析にかなり新しいです。なぜこれは決して減らされませんか?

答えて

2

あなたはパーサにあなたのエントリポイントが

%start <Ast.t> main 

mainと呼ばれている。しかし、私はあなたのコードでmain生産を見ることができないことを宣言します。エントリーポイントはyamlと思われますか?それが変更された場合 - エラーは引き続き発生しますか?また


、このように、あなたのレクサーに、エントリレベルの生産にEOFトークンを追加してみてください:

parse_yaml: yaml EOF { $1 } 

は、例えばここを参照してください:https://github.com/Virum/compiler/blob/28e807b842bab5dcf11460c8193dd5b16674951f/grammar.mly#L56

以下の実世界のOCamlへのリンクEOLの使い方についても議論しています。これがあなたの問題を解決すると思います。


ところで、あなたはOCamlにYAMLパーサーを書いていることを本当に冷静にしています。オープンソースにすれば、コミュニティにとって本当に便利なはずです。 YAMLは字下げに敏感なので、Menhirと解析するためには、あなたのレクサーによってINDENTDEDENTのトークンを生成する必要があります。また、YAMLはJSONの厳密なスーパーセットです。つまり、JSONサブセットから開始して展開することができます(またはそうでないかもしれない)ことを意味します。実世界のOCamlは立石を使用してJSONパーサーを作成する方法を示しています

https://dev.realworldocaml.org/16-parsing-with-ocamllex-and-menhir.html

+0

これはYAMLパーサの冒頭で、私はすでに非常に基本的に苦しんだので、私は、 '' main'にyaml'と改名しました。 :D reduce問題は 'yaml'変種から発生します。 私はrealworldocamlを試してみよう。 – Seneca

+0

@Seneca私の更新された答えを見てください。 – Halst

+0

本当にそれをしたEOFでした! – Seneca

関連する問題