[Haskell-cafe] Overlaping Parsec rules

Hauschild, Klaus (EXT) klaus.hauschild.ext at siemens.com
Mon Mar 7 11:34:40 CET 2011


Hi,

to solve this ICFP task http://www.cs.cornell.edu/icfp/task.htm I'm currnetly working on the parser. With the hint from Thu (reading Phillip Wadlers monadic parser paper) and consulting http://en.wikibooks.org/wiki/Write_Yourself_a_Scheme_in_48_Hours/Parsing I produce a first working version of the parser.
After this great moment I completed the token definition and near all parsing rules. For the complete code have a look at http://code.google.com/p/hgmltracer/source/browse/#svn%2Ftrunk%2FhGmlTracer

data GmlToken =

        -- structures

        FunctionToken TokenSequence     |

        ArrayToken TokenSequence        |

        -- control operators

        ApplyToken                      |

        IfToken                         |

        -- number operators

        AddiToken                       |

        AddfToken                       |

        ACosToken                       |

        ASinToken                       |

        ClampfToken                     |

        CosToken                        |

        DiviToken                       |

        DivfToken                       |

        EqiToken                        |

        EqfToken                        |

        FloorToken                      |

        FracToken                       |

        LessiToken                      |

        LessfToken                      |

        ModiToken                       |

        MuliToken                       |

        MulfToken                       |

        NegiToken                       |

        NegfToken                       |

        ToRealToken                     |

        SinToken                        |

        SqrtToken                       |

        SubiToken                       |

        SubfToken                       |

        -- points

        GetXToken                       |

        GetYToken                       |

        GetZToken                       |

        PointToken                      |

        -- arrays

        GetToken                        |

        LengthToken                     |

        -- environment

        IdentifierToken String          |

        BinderToken String              |

        -- types

        BoolToken Bool                  |

        IntToken Int                    |

        RealToken Double                |

        StringToken String              deriving Show

And

parseGml :: String -> [GmlToken]

parseGml input = case parse parseList "gml" input of

    Left err -> error ("Parse error: " ++ (show err))

    Right gml -> gml



parseList = sepBy parseGml' spaces



parseGml' =

        -- structures

--        parseFunction

--    <|> parseArray

        -- control operators

        parseControlOperators

        -- number operators

    <|> parseNumberOperators

        -- points

    <|> parsePointOperators

        -- arrays

    <|> parseArrayOperators

        -- types

    <|> parseBool

    <|> parseInteger

    <|> parseString

        -- environment

    <|> parseIdentifier

    <|> parseBinder



parseArray = parseSequence '[' ']'

parseFunction = parseSequence '{' '}'

parseSequence start end = do char start

                             array <- parseList

                             char end

                             return $ ArrayToken array



parseControlOperators = parseApply <|> parseIf

parseApply = do string "apply"

                return $ ApplyToken

parseIf = do string "if"

             return $ IfToken



parseNumberOperators = do string "addi"

                          return $ AddiToken

                   <|> do string "addf"

                          return $ AddfToken

                   <|> do string "acos"

                          return $ ACosToken

                   <|> do string "asind"

                          return $ ASinToken

                   <|> do string "clampf"

                          return $ ClampfToken

                   <|> do string "cos"

                          return $ CosToken

                   <|> do string "divi"

                          return $ DiviToken

                   <|> do string "divf"

                          return $ DivfToken

                   <|> do string "eqi"

                          return $ EqiToken

                   <|> do string "eqf"

                          return $ EqfToken

                   <|> do string "floor"

                          return $ FloorToken

                   <|> do string "frac"

                          return $ FracToken

                   <|> do string "lessi"

                          return $ LessiToken

                   <|> do string "lessf"

                          return $ LessfToken

                   <|> do string "modi"

                          return $ ModiToken

                   <|> do string "muli"

                          return $ MuliToken

                   <|> do string "mulf"

                          return $ MulfToken

                   <|> do string "negi"

                          return $ NegiToken

                   <|> do string "negf"

                          return $ NegfToken

                   <|> do string "real"

                          return $ ToRealToken

                   <|> do string "sin"

                          return $ SinToken

                   <|> do string "Sqrt"

                          return $ SqrtToken

                   <|> do string "subi"

                          return $ SubiToken

                   <|> do string "subf"

                          return $ SubfToken



parsePointOperators = do string "getx"

                         return $ GetXToken

                  <|> do string "gety"

                         return $ GetYToken

                  <|> do string "getz"

                         return $ GetZToken

                  <|> do string "point"

                         return $ PointToken



parseArrayOperators = do string "get"

                         return $ GetToken

                  <|> do string "length"

                         return $ LengthToken



parseInteger = liftM (IntToken . read) $ many1 digit

parseBool = do string "true"

               return $ BoolToken True

        <|> do string "false"

               return $ BoolToken False

parseString = do char '"'

                 string <- many (noneOf "\"")

                 char '"'

                 return $ StringToken string



parseIdentifier = do identifier <- many (noneOf " ")

                     return $ IdentifierToken identifier

parseBinder = do char '/'

                 binder <- many (noneOf " ")

                 return $ BinderToken binder



parseComment = do char '%'

                  many (noneOf "")

                  newline

                  return $ ()



spaces = skipMany1 space


After gluing all this together in my mind all worked well. But it doesn't. The test file for parsing looks like:

{ /self /n
  n 2 lessi
  { 1 }
  { n 1 subi self self apply n muli }
  if
} /fact

12 fact fact apply

*       I think there is a problem with overlaping rules. There is a parser rule consuming "negi" and resulting in the NegiToken. A single "n" is a valid identifier. For the example file my parser says: unexpected " ", expecting "negi"
*       I think the same problem is present for "parseInteger" and "parseReal" (currently no in code but looks like "parseReal = do a <- many1 digit \n char '.' \n b <- many1 digit \n return $ RealToken (read (a ++ "." ++ b)"
*       Something with "parseFunction" is going really wrong.
*       All parsig rules are designed with the condition that each "construct" is separated by whitespaces. For this before parsing the input will be preprocessed: insert spaces, removing whitespaces and so on. Now in the parsed result appears (IdentifierToken ""). I think my version is not the best way to parse a identifer:
parseIdentifier = do identifier <- many (noneOf " ")
                     return $ IdentifierToken identifier

Please help me.

Klaus

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/haskell-cafe/attachments/20110307/82a6c488/attachment-0001.htm>


More information about the Haskell-Cafe mailing list