marc walter

Parsing IPv4 addresses in elm

2018-12-29 (Last updated on 2018-12-29)

The elm parser has problems when trying to parse an integer number followed by a dot ("."), issue 14 describes this problem.

There is a nice solution on the elm discourse platform from dmy, which also demonstrates how to chomp a string using chompWhile and getChompedString.

Full code:

module Main exposing (main)

import Html exposing (text)
import Parser exposing (Parser, (|=), (|.), symbol)


type alias IPv4 =
    { a : Int
    , b : Int
    , c : Int
    , d : Int
    , mask : Int
    }


intRange : Int -> Int -> Parser Int
intRange from to =
    Parser.getChompedString (Parser.chompWhile Char.isDigit)
        |> Parser.andThen (checkRange from to)


checkRange : Int -> Int -> String -> Parser Int
checkRange from to str =
    case String.toInt str of
        Just n ->
            if n >= from && n <= to then
                Parser.succeed n

            else
                rangeProblem from to

        Nothing ->
            rangeProblem from to


rangeProblem : Int -> Int -> Parser a
rangeProblem from to =
    [ "expected a number between"
    , String.fromInt from
    , "and"
    , String.fromInt to
    ]
        |> String.join " "
        |> Parser.problem


ipv4 : Parser IPv4
ipv4 =
    Parser.succeed IPv4
        |= intRange 0 255
        |. symbol "."
        |= intRange 0 255
        |. symbol "."
        |= intRange 0 255
        |. symbol "."
        |= intRange 0 255
        |. symbol "/"
        |= intRange 0 32


main =
    Parser.run ipv4 "192.168.0.1/32"
        |> Debug.toString 
        |> text