diff --git a/CHANGELOG.markdown b/CHANGELOG.markdown
--- a/CHANGELOG.markdown
+++ b/CHANGELOG.markdown
@@ -1,3 +1,7 @@
+0.1.2.0
+-------
+* relax the grammer of OPB/WBO files to allow various use of space characters.
+
 0.1.1.0
 -------
 * parse* functions fails if the parser does not consume all of the inputs
diff --git a/pseudo-boolean.cabal b/pseudo-boolean.cabal
--- a/pseudo-boolean.cabal
+++ b/pseudo-boolean.cabal
@@ -2,7 +2,7 @@
 -- documentation, see http://haskell.org/cabal/users-guide/
 
 name:                pseudo-boolean
-version:             0.1.1.0
+version:             0.1.2.0
 synopsis:            Reading/Writing OPB/WBO files used in pseudo boolean competition
 description:         Reading\/Writing OPB\/WBO files used in pseudo boolean competition
 homepage:            https://github.com/msakai/pseudo-boolean
diff --git a/src/Data/PseudoBoolean/Attoparsec.hs b/src/Data/PseudoBoolean/Attoparsec.hs
--- a/src/Data/PseudoBoolean/Attoparsec.hs
+++ b/src/Data/PseudoBoolean/Attoparsec.hs
@@ -90,12 +90,13 @@
 comment = do
   _ <- char '*' 
   _ <- manyTill anyChar eol
+  skipMany space -- We relax the grammer and allow spaces in the beggining of next component.
   return ()
 
 -- <sequence_of_comments_or_constraints>::= <comment_or_constraint> [<sequence_of_comments_or_constraints>]
 sequence_of_comments_or_constraints :: Parser [Constraint]
 sequence_of_comments_or_constraints = do
-  xs <- many1 comment_or_constraint
+  xs <- many' comment_or_constraint -- XXX: we relax the grammer to allow empty sequence
   return $ catMaybes xs
 
 -- <comment_or_constraint>::= <comment>|<constraint>
@@ -109,8 +110,7 @@
   _ <- string "min:"
   zeroOrMoreSpace
   obj <- sum
-  _ <- char ';'
-  eol
+  semi
   return obj
 
 -- <constraint>::= <sum> <relational_operator> <zeroOrMoreSpace> <integer> <zeroOrMoreSpace> ";"
@@ -168,13 +168,16 @@
 
 -- <zeroOrMoreSpace>::= [" " <zeroOrMoreSpace>]
 zeroOrMoreSpace :: Parser ()
-zeroOrMoreSpace = skipMany (char ' ')
+-- zeroOrMoreSpace = skipMany (char ' ')
+zeroOrMoreSpace = skipSpace
+-- We relax the grammer and allow more type of spacing
 
 eol :: Parser ()
 eol = char '\n' >> return ()
 
 semi :: Parser ()
-semi = char ';' >> eol
+semi = char ';' >> skipSpace
+-- We relax the grammer and allow spaces in the beginning of next component.
 
 {-
 For linear pseudo-Boolean instances, <term> is defined as
@@ -237,7 +240,7 @@
 -- <sequence_of_comments_or_constraints>::= <comment_or_constraint> [<sequence_of_comments_or_constraints>]
 wbo_sequence_of_comments_or_constraints :: Parser [SoftConstraint]
 wbo_sequence_of_comments_or_constraints = do
-  xs <- many1 wbo_comment_or_constraint
+  xs <- many' wbo_comment_or_constraint -- We relax the grammer and allow spaces in the beginning of next component.
   return $ catMaybes xs
 
 -- <comment_or_constraint>::= <comment>|<constraint>|<softconstraint>
diff --git a/src/Data/PseudoBoolean/Parsec.hs b/src/Data/PseudoBoolean/Parsec.hs
--- a/src/Data/PseudoBoolean/Parsec.hs
+++ b/src/Data/PseudoBoolean/Parsec.hs
@@ -90,12 +90,13 @@
 comment = do
   _ <- char '*' 
   _ <- manyTill anyChar eol
+  spaces -- We relax the grammer and allow spaces in the beggining of next component.
   return ()
 
 -- <sequence_of_comments_or_constraints>::= <comment_or_constraint> [<sequence_of_comments_or_constraints>]
 sequence_of_comments_or_constraints :: Stream s m Char => ParsecT s u m [Constraint]
 sequence_of_comments_or_constraints = do
-  xs <- many1 comment_or_constraint
+  xs <- many comment_or_constraint -- We relax the grammer and allow spaces in the beginning of next component.
   return $ catMaybes xs
 
 -- <comment_or_constraint>::= <comment>|<constraint>
@@ -109,8 +110,7 @@
   _ <- string "min:"
   zeroOrMoreSpace
   obj <- sum
-  _ <- char ';'
-  eol
+  semi
   return obj
 
 -- <constraint>::= <sum> <relational_operator> <zeroOrMoreSpace> <integer> <zeroOrMoreSpace> ";"
@@ -168,13 +168,16 @@
 
 -- <zeroOrMoreSpace>::= [" " <zeroOrMoreSpace>]
 zeroOrMoreSpace :: Stream s m Char => ParsecT s u m ()
-zeroOrMoreSpace = skipMany (char ' ')
+-- zeroOrMoreSpace = skipMany (char ' ')
+zeroOrMoreSpace = spaces
+-- We relax the grammer and allow more type of spacing
 
 eol :: Stream s m Char => ParsecT s u m ()
 eol = char '\n' >> return ()
 
 semi :: Stream s m Char => ParsecT s u m ()
-semi = char ';' >> eol
+semi = char ';' >> spaces
+-- We relax the grammer and allow spaces in the beginning of next component.
 
 {-
 For linear pseudo-Boolean instances, <term> is defined as
@@ -240,7 +243,7 @@
 -- <sequence_of_comments_or_constraints>::= <comment_or_constraint> [<sequence_of_comments_or_constraints>]
 wbo_sequence_of_comments_or_constraints :: Stream s m Char => ParsecT s u m [SoftConstraint]
 wbo_sequence_of_comments_or_constraints = do
-  xs <- many1 wbo_comment_or_constraint
+  xs <- many wbo_comment_or_constraint -- XXX: we relax the grammer to allow empty sequence
   return $ catMaybes xs
 
 -- <comment_or_constraint>::= <comment>|<constraint>|<softconstraint>
diff --git a/test/TestPBFile.hs b/test/TestPBFile.hs
--- a/test/TestPBFile.hs
+++ b/test/TestPBFile.hs
@@ -62,6 +62,130 @@
       , "foo"
       ]
 
+case_min_eol = do
+  isOk (parseOPBString "" opb) @?= True
+  isOk (parseOPBByteString "" (BSChar8.pack opb)) @?= True
+  isOk (A.parseOPBByteString (BSChar8.pack opb)) @?= True
+  where
+    -- isLeft is available only on base >=4.7.0.0.
+    isOk :: Either a b -> Bool
+    isOk (Left _) = False
+    isOk (Right _) = True
+    
+    opb = unlines
+      [ "* #variable= 5 #constraint= 4"
+      , "*"
+      , "* this is a dummy instance"
+      , "*"
+      , "min: "
+      , "1 x2 -1 x3 ;"
+      , "1 x1 +4 x2 -2 x5 >= 2;"
+      , "-1 x1 +4 x2 -2 x5 >= +3;"
+      , "12345678901234567890 x4 +4 x3 >= 10;"
+      , "* an equality constraint"
+      , "2 x2 +3 x4 +2 x1 +3 x5 = 5;"
+      ]
+
+case_empty_constraints = do
+  isOk (parseOPBString "" opb) @?= True
+  isOk (parseOPBByteString "" (BSChar8.pack opb)) @?= True
+  isOk (A.parseOPBByteString (BSChar8.pack opb)) @?= True
+  where
+    -- isRight is available only on base >=4.7.0.0.
+    isOk :: Either a b -> Bool
+    isOk (Left _) = False
+    isOk (Right _) = True
+    
+    opb = unlines
+      [ "* #variable= 3 #constraint= 0"
+      , "min: 1 x2 -1 x3 ;"
+      ]
+
+case_wbo_empty_constraints = do
+  isOk (parseWBOString "" wbo) @?= True
+  isOk (parseWBOByteString "" (BSChar8.pack wbo)) @?= True
+  isOk (A.parseWBOByteString (BSChar8.pack wbo)) @?= True
+  where
+    -- isRight is available only on base >=4.7.0.0.
+    isOk :: Either a b -> Bool
+    isOk (Left _) = False
+    isOk (Right _) = True
+    
+    wbo = unlines
+      [ "* #variable= 0 #constraint= 0"
+      , "soft: 1 ;"
+      ]
+
+case_trailing_spaces_before_eol = do
+  isOk (parseOPBString "" opb) @?= True
+  isOk (parseOPBByteString "" (BSChar8.pack opb)) @?= True
+  isOk (A.parseOPBByteString (BSChar8.pack opb)) @?= True
+  where
+    -- isRight is available only on base >=4.7.0.0.
+    isOk :: Either a b -> Bool
+    isOk (Left _) = False
+    isOk (Right _) = True
+    
+    opb = unlines
+      [ "* #variable= 5 #constraint= 4"
+      , "*"
+      , "* this is a dummy instance"
+      , "*"
+      , "min: 1 x2 -1 x3 ;"
+      , "1 x1 +4 x2 -2 x5 >= 2; "
+      , "-1 x1 +4 x2 -2 x5 >= +3; "
+      , "12345678901234567890 x4 +4 x3 >= 10; "
+      , "* an equality constraint "
+      , "2 x2 +3 x4 +2 x1 +3 x5 = 5; "
+      ]
+
+case_trailing_spaces_before_eof = do
+  isOk (parseOPBString "" opb) @?= True
+  isOk (parseOPBByteString "" (BSChar8.pack opb)) @?= True
+  isOk (A.parseOPBByteString (BSChar8.pack opb)) @?= True
+  where
+    -- isRight is available only on base >=4.7.0.0.
+    isOk :: Either a b -> Bool
+    isOk (Left _) = False
+    isOk (Right _) = True
+    
+    opb = unlines
+      [ "* #variable= 5 #constraint= 4"
+      , "*"
+      , "* this is a dummy instance"
+      , "*"
+      , "min: 1 x2 -1 x3 ;"
+      , "1 x1 +4 x2 -2 x5 >= 2;"
+      , "-1 x1 +4 x2 -2 x5 >= +3;"
+      , "12345678901234567890 x4 +4 x3 >= 10;"
+      , "* an equality constraint"
+      , "2 x2 +3 x4 +2 x1 +3 x5 = 5;"
+      , "        "
+      ]
+
+case_leading_spaces = do
+  isOk (parseOPBString "" opb) @?= True
+  isOk (parseOPBByteString "" (BSChar8.pack opb)) @?= True
+  isOk (A.parseOPBByteString (BSChar8.pack opb)) @?= True
+  where
+    -- isRight is available only on base >=4.7.0.0.
+    isOk :: Either a b -> Bool
+    isOk (Left _) = False
+    isOk (Right _) = True
+    
+    opb = unlines
+      [ "* #variable= 5 #constraint= 4"
+      , "*"
+      , "* this is a dummy instance"
+      , "*"
+      , "min: 1 x2 -1 x3 ;"
+      , "   1 x1 +4 x2 -2 x5 >= 2;"
+      , "   -1 x1 +4 x2 -2 x5 >= +3;"
+      , "   12345678901234567890 x4 +4 x3 >= 10;"
+      , "* an equality constraint"
+      , "   2 x2 +3 x4 +2 x1 +3 x5 = 5;"
+      ]
+
 case_readUnsignedInteger_maxBound_bug :: IO ()
 case_readUnsignedInteger_maxBound_bug =
   readUnsignedInteger "006666666666666667" @?= 6666666666666667
