2017-05-15 34 views
1

我想用Token list -> Ast * Token list類型構建活動模式。在遞歸下降解析器中縮短活動模式

我有一個簡單的帕斯卡語法<program> ::= "program" <id> ";" <block> "."。通過重構代碼,這個語法,我必須做出ProgramIdentifierBlock模式,如:

let rec (|Program|_|) tokens = 
    match tokens with 
    | Token.Program :: tokens -> 
     match tokens with 
     | Identifier (identifier, tokens) -> 
      match tokens with 
      | Semicolon :: tokens -> 
       match tokens with 
       | Block (block, tokens) -> 
        match tokens with 
        | Dot :: tokens -> Some (Ast.Program (identifier, block), tokens) 
        | _ -> failwithf "Expected %A" Dot 
       | _ -> failwith "Expected Block" 
      | _ -> failwithf "Expected %A" Semicolon 
     | _ -> failwith "Expected Identifier" 
    | _ -> failwithf "Expected %A" Token.Program 

and (|Identifier|_|) tokens = 
    match tokens with 
    | Token.Identifier identifier :: tokens -> 
     Some (Ast.Identifier identifier, tokens) 
    | _ -> failwith "Expected Identifier" 
... 

因爲有很多重複的選項None,我試圖縮短模式是:

type rec (|Program|_|) tokens = 
    match tokens with 
    | Token.Program :: Identifier (ident, Semicolon :: Block (block, Dot :: rest)) -> 
     Some (Ast.Program (identifier, block), rest) 
    | _ -> None 

新模式能否按預期工作?我怎樣才能使活動模式更短,但不知怎的,也會返回錯誤輸入的錯誤?

另外,我讀到FParsec使用monad來分析和保留錯誤,我怎樣才能做出類似FParsec的簡單計算表達式。

+0

對於編寫計算表達式,https://fsharpforfunandprofit.com/series/computation-expressions.html是你最好的指導。 – rmunn

+0

另外,您的AST設計對我來說看起來有點奇怪。爲什麼「標識符」和「塊」聯合案例吸收了「內部」中的以下標記,但「程序」標記沒有?我期望看到一些更類似於具有標識符ident :: tokens的匹配令牌,即只有「標識符」情況「吸收」了標識符的名稱。 「標識符」情況下的所有以下標記都沒有意義。我不知道我是否清楚地傳達了我想說的話;你明白我的意思嗎,還是應該嘗試重新翻譯它? – rmunn

+0

@rmunn所有活動模式吸收令牌並返回剩餘的模式。因爲我從http://stackoverflow.com/a/4418823/7821462閱讀,他們應該有類型'令牌列表 - > Ast *令牌列表。 – MiP

回答

1

簡單的方法就是拉平一切:

let rec private (|Program|_|) tokens = 
    match tokens with 
    | Token.Program ::Identifier (identifier, Semicolon :: Block (block,Dot :: tokens)) ->Some (Ast.Program (identifier, block), tokens) 
    | Token.Program ::Identifier (identifier, Semicolon :: Block (block,_)) ->failwith "Expected %A" Dot 
    | Token.Program ::Identifier (identifier, Semicolon ::_) ->failwith "Expected %A" Block 
.... 
+0

你知道如何sprintf標識符或塊嗎?例如當我有'類型Token = |字符串標識符「,我想宣佈」預期標識符「和」failwithf「預期%A」(標識符「」)不能按預期工作。 – MiP

+0

想不到任何東西 –