如何解析无序语法
How to parse unordered syntax
newtype Program = Program [Global] [Function]
我正在 Haskell 中使用类 C 语法解析源文件,其中全局变量和函数位于顶层。解析它们是否必须按顺序排列很简单,比方说,函数在所有全局变量之后。但它们可以按任何顺序出现,如下所示。如何处理这样的语法?
global0
function0
global1
function1
function2
global2
似乎可以使用 Parsec.Perm 之类的东西,但是当所有选择 return 相同类型(decimal)时 the example 有效,其中对于我的情况 returns Global 或 Function.
您不需要排列解析器。简单的旧 many
就可以了。您可以使用 Either
暂时使它们成为同一类型,然后 partitionEithers
将它们分开。
uncurry Program . partitionEithers
<$> many ( (Left <$> parseGlobal)
<|> (Right <$> parseFunction)
)
编辑:或者,您可以将它们全部设为 Program
,然后将它们合并。像
instance Monoid Program where mempty = Program [] []
instance Semigroup Program where
Program gs fs <> Program gs' fs' = Program (gs <> gs') (fs <> fs')
global x = Program [x] []
function x = Program [] [x]
然后使用:
fold <$> many ((global <$> parseGlobal) <|> (function <$> parseFunction))
非常相似的程序结构,但也许其中一种更适合您。
newtype Program = Program [Global] [Function]
我正在 Haskell 中使用类 C 语法解析源文件,其中全局变量和函数位于顶层。解析它们是否必须按顺序排列很简单,比方说,函数在所有全局变量之后。但它们可以按任何顺序出现,如下所示。如何处理这样的语法?
global0
function0
global1
function1
function2
global2
似乎可以使用 Parsec.Perm 之类的东西,但是当所有选择 return 相同类型(decimal)时 the example 有效,其中对于我的情况 returns Global 或 Function.
您不需要排列解析器。简单的旧 many
就可以了。您可以使用 Either
暂时使它们成为同一类型,然后 partitionEithers
将它们分开。
uncurry Program . partitionEithers
<$> many ( (Left <$> parseGlobal)
<|> (Right <$> parseFunction)
)
编辑:或者,您可以将它们全部设为 Program
,然后将它们合并。像
instance Monoid Program where mempty = Program [] []
instance Semigroup Program where
Program gs fs <> Program gs' fs' = Program (gs <> gs') (fs <> fs')
global x = Program [x] []
function x = Program [] [x]
然后使用:
fold <$> many ((global <$> parseGlobal) <|> (function <$> parseFunction))
非常相似的程序结构,但也许其中一种更适合您。