haskell中文件结尾意外

时间:2014-02-04 11:09:20

标签: haskell parsec

我想我已经非常努力地研究了我的问题所以我在这里。

我有一个“文件意外结束”错误 6 colunm 33。

我已经尝试了很多解决方案来解决我的问题。

这是我的代码和我要解析的文件。

以下是我要解析的文字:

ifc.txt:

#9512= IFCBUILDINGSTOREY('3y21AUC9X4yAqzLGUny16E',#16,'Story',$,$,#9509,$,$,.ELEMENT.,6200.);
#9509= IFCLOCALPLACEMENT(#115,#9506);
#9506= IFCAXIS2PLACEMENT3D(#9502,#9498,#9494);
#9502= IFCCARTESIANPOINT((0.,0.,6200.));
#9498= IFCDIRECTION((0.,0.,1.));
#9494= IFCDIRECTION((1.,0.,0.));

以下是代码:

code.hs:

import Text.ParserCombinators.Parsec
main = do
  f <- readFile "ifc.txt"
  let m = (parse ifc "" f)
  print m

ifc :: Parser IfcModel
ifc = many ifcentry

ifcentry = do
  string "#"
  i <- idt
  string "= "
  name <- idt
  string "("
  prop <- idt
  string ")"
  string ";"
  string "\n"
  return (i,name,prop)

idt = many (letter <|> digit <|> char ','
   <|> char '$' <|> char ')' <|> char '\''
   <|> char '=' <|> char ';'  <|> char '\n'
   <|> char ' ' <|> char '(' <|> char '#'
   <|> char '.' <|> char '\r')

感谢你的帮助,我应该早点检查一下我的anwser,因为我自己工作,我发现asolution我会发布它,当我可以(8小时左边的新手像我一样,声誉低于10)

再次感谢。

3 个答案:

答案 0 :(得分:4)

解决方案:使用sepBy而不是在ifcentry

中包含换行符

你的ifcentry期望最后一行换行,而你的输入没有换行,这就是EOF出乎意料的原因。

string "\n"删除ifcentry,然后定义

ifc :: Parser IfcModel
ifc = ifcentry `sepBy` (char '\n')

此外,您的idt解析器不必要很长。

会更清楚
idt = many (letter <|> digit <|> oneOf ".,;' =#$()\n\r")

更清楚ifcentry

虽然我在,但我会写

ifcentry = do
  char '#'
  i <- idt
  string "= "
  name <- idt
  prop <- parens idt
  char ';'
  return (i,name,prop)

因为parens(解析一个空心括号,你的idt内容,然后是一个小括号)整理它并使其更清晰。

少详细main

我也写

main = fmap (parse ifc "") (readFile "ifc.txt") >>= print

当然不需要

  let m = (parse ifc "" f)
  print m

因为你也可以这样做

  print (parse ifc "" f)

答案 1 :(得分:1)

另外还有@enough rep回复评论的答案

我会更进一步,并在

的行中声明一些内容
data IFCType = IFCBuildingStorey ....
             | IFCLocalPlacement ....
             | IFCAxis2Placement3D ....
             | IFCCartesianpoint Double Double Double
             | IFCDirection ....
             deriving Show

type ID = Integer
type IFCElement = (ID,IFCType)

我将以CartesianPoint为例展示

ifctype :: Parser IFCType
ifctype = do string "IFC"
             buildingStorey
             <|> localPlacement
             <|> axis2Placement3D
             <|> cartesianpoint
             <|> direction

buildingStorey :: Parser IFCType
buildingStorey = do string "BUILDINGSTOREY"
                    return IFCBuildingStorey

localPlacement :: Parser IFCType
localPlacement = do string "LOCALPLACEMENT"
                    return IFCLocalPlacement

axis2Placement3D :: Parser IFCType
axis2Placement3D = do string "AXIS2PLACEMENT3D"
                      return IFCAxis2Placement3D

cartesianpoint :: Parser IFCType
cartesianpoint = do string "CARTESIANPOINT"
                    char '('
                    char '('
                    x <- double
                    char ','
                    y <- double
                    char ','
                    z <- double
                    char ')'
                    char ')'
                    return $ IFCCartesianpoint x y z

double :: Parser Double
double = do d <- many1 (digit <|> char '.')
            return $ read d

direction :: Parser IFCType
direction = do string "DIRECTION"
               return IFCDirection

这具有您输入模型的额外优势。

答案 2 :(得分:0)

感谢大家的帮助,我应该早点检查一下,因为我自己工作并最终找到了解决方案:

import Text.ParserCombinators.Parsec

main = do
 f <- readFile "ifc.txt"
 let m = (parse ifc "" f)
 print m

type IfcIdt = String
type IfcName = String
type IfcProp = [String]
type IfcModel = [(IfcIdt,IfcName,IfcProp)]

ifc :: Parser IfcModel
ifc = many ifcentry

ifcentry = do
 string "#"
 i <- idtnumber
 string "= "
 name <- idtname
 opening
 prop <- ifcprop
 closing
 eol
 return (i,name,prop)

idtnumber = many digit
idtname = many (letter <|> digit)

ifcprop = sepBy prop (char ',')
prop = many (noneOf "=,();\n")
eol = string ";\n"
opening = try (string "((")
 <|> string "("
closing = try (string "))")
 <|> string ")"