Haskell - Parsec :: 解析空格直到字符串文字
Haskell - Parsec :: Parse spaces until string literal
我目前正在尝试使用 Parsec 在 Haskell 中设计一个解析器。
声明类型的语法应该是这样的:
Fruit is a Apple
类型也应该可以有参数:
Fruit a b is a Apple
在哪里
Fruit
的类型为 Name
a b
的类型为 [Parameter]
Apple
的类型为 Value
这里的问题是我的解析器目前不知道什么时候停止解析 parameters
并开始解析 value
.
代码如下:
newtype Name = Name String deriving (Show)
newtype Parameter = Parameter String deriving (Show)
newtype Value = Value String deriving (Show)
data TypeAssignment = TypeAssignment Name [Parameter] Value deriving (Show)
-- first variant using `sepBy`
typeAssigment :: Parser TypeAssignment
typeAssigment =
TypeAssignment
<$> name
<*> (space *> parameter `sepBy` space)
<*> (string "is a" *> value)
-- second variant using manyTill
typeAssigment2 :: Parser TypeAssignment
typeAssigment2 =
TypeAssignment
<$> name
<*> (space *> manyTill parameter (string "is a"))
<*> value
name :: Parser Name
name = Name <$> word
parameter :: Parser Parameter
parameter = Parameter <$> word
value :: Parser Value
value = Value <$> word
word :: Parser String
word = (:) <$> letter <*> many (letter <|> digit)
我已经尝试以两种我知道如何解析 parameters/value 的方式(一次使用 sepBy,一次使用 manyTill)都失败了,几乎出现了解析错误:
*EParser> parseTest typeAssigment "Fruit a b is a Apple"
parse error at (line 1, column 21):
unexpected end of input
expecting space or "is a"
*EParser> parseTest typeAssigment2 "Fruit a b is a Apple"
parse error at (line 1, column 8):
unexpected " "
expecting letter, digit or "is a"
typeAssignment1
的问题在于 "is"
和 "a"
是完全有效的 parameter
解析。所以,参数解析吞噬了整个输入,直到什么都没有留下,然后你会得到一个错误。事实上,如果您仔细查看该错误,您会发现这是真的:解析器期望 space(更多参数)或“is a”(整个解析器的终端)。
另一方面,typeAssignment2
非常接近,但您似乎没有正确处理 space。为了解析许多 parameter
,您需要解析这些参数之间的所有 space
,而不仅仅是第一个。
我认为以下替代方案应该可以解决问题:
typeAssigment3 :: Parser TypeAssignment
typeAssigment3 =
TypeAssignment
<$> name
<*> manyTill (space *> parameter) (try $ string "is a")
<*> (space *> value)
我目前正在尝试使用 Parsec 在 Haskell 中设计一个解析器。 声明类型的语法应该是这样的:
Fruit is a Apple
类型也应该可以有参数:
Fruit a b is a Apple
在哪里
Fruit
的类型为Name
a b
的类型为[Parameter]
Apple
的类型为Value
这里的问题是我的解析器目前不知道什么时候停止解析 parameters
并开始解析 value
.
代码如下:
newtype Name = Name String deriving (Show)
newtype Parameter = Parameter String deriving (Show)
newtype Value = Value String deriving (Show)
data TypeAssignment = TypeAssignment Name [Parameter] Value deriving (Show)
-- first variant using `sepBy`
typeAssigment :: Parser TypeAssignment
typeAssigment =
TypeAssignment
<$> name
<*> (space *> parameter `sepBy` space)
<*> (string "is a" *> value)
-- second variant using manyTill
typeAssigment2 :: Parser TypeAssignment
typeAssigment2 =
TypeAssignment
<$> name
<*> (space *> manyTill parameter (string "is a"))
<*> value
name :: Parser Name
name = Name <$> word
parameter :: Parser Parameter
parameter = Parameter <$> word
value :: Parser Value
value = Value <$> word
word :: Parser String
word = (:) <$> letter <*> many (letter <|> digit)
我已经尝试以两种我知道如何解析 parameters/value 的方式(一次使用 sepBy,一次使用 manyTill)都失败了,几乎出现了解析错误:
*EParser> parseTest typeAssigment "Fruit a b is a Apple"
parse error at (line 1, column 21):
unexpected end of input
expecting space or "is a"
*EParser> parseTest typeAssigment2 "Fruit a b is a Apple"
parse error at (line 1, column 8):
unexpected " "
expecting letter, digit or "is a"
typeAssignment1
的问题在于 "is"
和 "a"
是完全有效的 parameter
解析。所以,参数解析吞噬了整个输入,直到什么都没有留下,然后你会得到一个错误。事实上,如果您仔细查看该错误,您会发现这是真的:解析器期望 space(更多参数)或“is a”(整个解析器的终端)。
另一方面,typeAssignment2
非常接近,但您似乎没有正确处理 space。为了解析许多 parameter
,您需要解析这些参数之间的所有 space
,而不仅仅是第一个。
我认为以下替代方案应该可以解决问题:
typeAssigment3 :: Parser TypeAssignment
typeAssigment3 =
TypeAssignment
<$> name
<*> manyTill (space *> parameter) (try $ string "is a")
<*> (space *> value)