2017-08-10 109 views
1

我試圖寫的一個小骰子符號解析骰子符號(例如,「2D6」,其中2count6是死size)使用所述文庫中elm-tools/parser解析器。用榆樹

的表達式應該是在形式

[int] "d" int 

,但我想不出來解析可選領先int(這將默認爲1,如果缺少它)。

到目前爲止,我已經想出了這一點:

import Parser exposing (..) 


type alias Roll = 
    { count : Int 
    , size : Int 
    } 


die : Parser Int 
die = 
    succeed identity 
     |. keyword "d" 
     |= int 

,我想解析器上一次成功的解析返回一個Roll,但我不知道如何着手。

我猜我需要使用oneOf,但我不知道如何。

不幸的是,我找不到使用這個庫的任何好例子。

回答

0

感謝@乍得的答案(https://stackoverflow.com/a/45620875/96233),我知道了這個工作:

type alias Dice = 
    { count : Int 
    , size : Int 
    } 


dice : Parser Dice 
dice = 
    succeed Dice 
     |= count 
     |. spaces 
     |. keyword "d" 
     |. spaces 
     |= integer 


count : Parser Int 
count = 
    oneOf 
     [ integer |> andThen succeed 
     , succeed 1 
     ] 


integer : Parser Int 
integer = 
    keep oneOrMore isDigit 
     |> andThen 
      (\s -> 
       case String.toInt s of 
        Ok value -> 
         succeed value 

        Err err -> 
         fail err 
      ) 


spaces : Parser() 
spaces = 
    ignore zeroOrMore (\c -> c == ' ') 
+0

這個答案[不解析你給出的''2d6「'](https://ellie-app.com/3YVLMkCqM6ra1/0)的原始示例,因爲'int'如果遇到字母數字字符,則失敗。然而,如果你在'2'後有一個空格,它會成功。你有沒有改變要求? –

+0

不,我現在正在用「private」整數解析器而不是「int」修復代碼。看起來'int'在'd'上被混淆了,因爲它是一個合法的十六進制數字。 – Ralph

+0

如果乍得的答案幫助了你,你應該加入它,也許接受它作爲最有用的答案。 – rubystallion

2

你可以先寫一個解析器,可選解析爲int,如果沒有被消耗掉,然後返回一個默認值:

optionalInt : Int -> Parser Int 
optionalInt default = 
    keep zeroOrMore Char.isDigit 
     |> andThen 
      (\str -> 
       case str of 
        "" -> 
         succeed default 

        digits -> 
         case String.toInt digits of 
          Ok val -> 
           succeed val 

          Err err -> 
           fail err 
      ) 

現在你可以使用這個解析器創建一個解析器爲Roll

roll : Parser Roll 
roll = 
    succeed Roll 
     |= optionalInt 1 
     |. keyword "d" 
     |= int 
+0

更正'count'和'size'。我會更新我的問題以澄清。 – Ralph

+0

謝謝,我已經刪除了關於歧義的陳述 –