嵌套解析器在快乐/无限循环中?

时间:2011-01-02 17:50:42

标签: haskell happy

我正在努力为一个简单的标记语言编写解析器。目前,我在infinit循环和嵌套元素方面遇到了一些问题。

我的标记语言基本上由两个元素组成,一个用于“普通”文本,另一个用于粗体/强调文本。

data Markup
    = MarkupText   String
    | MarkupEmph   [Markup]

例如,像Foo *bar*这样的文字应该被解析为[MarkupText "Foo ", MarkupEmph [MarkupText "bar"]]

该示例的Lexing工作正常,但解析它导致无限循环 - 我无法理解为什么。这是我目前的做法:

-- The main parser: Parsing a list of "Markup"
Markups     :: { [Markup] }
            : Markups Markup                    { $1 ++ [$2] }
            | Markup                            { [$1]       }

-- One single markup element
Markup      :: { Markup }
            : '*' Markups1 '*'                  { MarkupEmph $2 }
            | Markup1                           { $1            }

-- The nested list inside *..*
Markups1    :: { [Markup] }
            : Markups1 Markup1                  { $1 ++ [$2] }
            | Markup1                           { [$1]       }

-- Markup which is always available:
Markup1     :: { Markup }
            : String                            { MarkupText $1 }

这种方法有什么问题?怎么可以解决?

更新:抱歉。 Lexing没有按预期工作。无限循环在词法分析器内部。抱歉。 :)

更新2:根据要求,我使用此作为词法分析器:

lexer :: String -> [Token]
lexer [] = []
lexer str@(c:cs)

    | c == '*'              = TokenSymbol "*"   : lexer cs
    -- ...more rules...
    | otherwise             = TokenString val   : lexer rest

  where (val, rest) = span isValidChar str
        isValidChar = (/= '*')

无限递归发生是因为我在lexer str的第一条规则中有lexer cs而不是'*'。没有看到它,因为我的实际代码有点复杂。 :)

1 个答案:

答案 0 :(得分:1)

自从我处理解析器生成器以来,已经有一段时间了。

看起来你需要一个LR(1)解析器,我不确定Happy是什么。一旦我写这个,我就是肯定的,有人可以纠正我。

如果您的解析器无法向前看,它将永远停留在此声明

Markups1    :: { [Markup] }
        : Markups1 Markup1 
        | Markup1

它会查找Markups1,然后查找Markups1。我可以猜到最好的,它不是向Markup1展望它是否是一个字符串。

尝试像这样重写

Markups1    :: { [Markup] }
        : Markup1 Markups1
        | 

基本上你希望它首先找到字符串,然后尝试查找另一个字符串,如果找不到它需要结束该语句。