2017-08-10 1 views
1

Ich versuche, eine kleine Würfel Notation zu schreiben (zum Beispiel „2W6“, wo 2 ist die count und 6 ist die sterben size) Parser der Bibliothek in elm-tools/parser verwenden.Parsing Würfel Schreibweise mit Elm

Ein Ausdruck in Form sein sollte

[int] "d" int 

aber ich kann nicht herausfinden, zu analysieren, die optionale führende int (die 1 ausfällt, wenn es fehlt).

Bisher habe ich mit diesem kommen:

import Parser exposing (..) 


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


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

und ich möchte den Parser eine Roll auf ein erfolgreiches Parse zurückzukehren, aber ich bin nicht sicher, wie es weitergeht.

Ich rate, dass ich oneOf verwenden muss, aber ich bin mir nicht sicher, wie.

Leider kann ich keine guten Beispiele für die Verwendung dieser Bibliothek finden.

Antwort

0

Dank @ Chad Antwort (https://stackoverflow.com/a/45620875/96233), bekam ich es mit dieser Arbeit:

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

Diese Antwort [analysiert nicht das ursprüngliche Beispiel, das Sie von '" 2d6 "'] (https://ellie-app.com/3YVLMkCqM6ra1/0) seit 'int' parsen schlägt fehl, wenn es ein alphanumerisches Zeichen trifft. Es wäre jedoch erfolgreich, wenn Sie ein Leerzeichen nach "2" hätten. Hast du die Anforderungen geändert? –

+0

Nein. Ich korrigiere den Code jetzt mit einem "privaten" 'integer' Parser anstelle von' int'. Es scheint, dass "int" auf dem "d" verwirrt wird, weil es eine legale Hexadezimalziffer ist. – Ralph

+0

Wenn die Antwort von Chad Ihnen geholfen hat, sollten Sie sie auffrischen und vielleicht als die hilfreichste Antwort akzeptieren. – rubystallion

2

Sie können zunächst einen Parser schreiben, die optional einen int parst und wenn nichts verbraucht wird, dann einen Standardwert zurück:

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 
      ) 

Jetzt können Sie diese Parser verwenden, um einen Parser für Roll zu erstellen:

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

Korrigieren Sie die 'count' und' size'. Ich werde meine Frage aktualisieren, um zu klären. – Ralph

+0

Danke, ich habe meine Aussage über Ambiguität entfernt –