为什么字符串的词法分析器规则优先于我的所有其他规则?

时间:2013-06-20 21:34:53

标签: parsing haskell lexer parser-generator alex

使用Alex lexer我正在创建一个lexer来标记化电子邮件“From headers”。这是一个示例标题:

From: "John Doe" <john@doe.org>

“John Doe”被称为“显示名称”,我们假设它可以包含任何ASCII字符。

同样,我们假设电子邮件地址的各个部分可以包含任何ASCII字符。

以下是我的Alex计划。当我在上面的“From header”上运行它时,我只得到一个令牌:

[TokenString "From: \"John Doe\" <john@doe.org>"]

显然这条规则:

$us_ascii_character+    { \s -> TokenString s }

优先于所有其他规则。为什么?

我认为优先级基于规则在我的程序中实际列出的顺序:检查输入字符串是否与第一个规则匹配,如果它不匹配则检查输入字符串是否匹配第二条规则,等等。否?

如何表达我的规则,以便词法分析器将“From标头”标记为这些标记:

From, :, "John Doe", <, john, @, doe, ., org, >

并且显示名称和电子邮件部分可以包含任何ASCII字符?

这是我的Alex lexer:

{
module Main (main) where
}

%wrapper "posn"

$digit      = 0-9           
$alpha      = [a-zA-Z]      
$us_ascii_character     = [\t\n\r\ !\"\#\$\%\&\'\(\)\*\+\,\-\.\/0123456789\:\;\<\=\>\?\@ABCDEFGHIJKLMNOPQRSTUVWXYZ\[\\\]\^_`abcdefghijklmnopqrstuvwxyz\{\|\}~\DEL]

tokens :-

  $white+           ;
  \(.*\)           ;
  From             { \s -> TokenFrom }
  :                { \s -> TokenColon }
  "                { \s -> TokenQuote }
  \<               { \s -> TokenLeftAngleBracket }
  >                { \s -> TokenRightAngleBracket }
  @                { \s -> TokenAtSign }
  \.               { \s -> TokenPeriod }
  $us_ascii_character+     { \s -> TokenString s }

{
-- Each action has type :: String -> Token

-- The token type:
data Token =
    TokenFrom                 |
    TokenColon                |
    TokenQuote                |
    TokenLeftAngleBracket     |
    TokenRightAngleBracket    |
    TokenAtSign               |
    TokenPeriod               |
    TokenString String      
    deriving (Eq,Show)

1 个答案:

答案 0 :(得分:4)

您误解了选择规则的规则:

  

当输入流匹配多个规则时,匹配输入流的最长前缀的规则将获胜。如果仍有多个规则匹配相同数量的字符,则规则它最早出现在文件中。

如上所述in the documentation。只有当多个规则匹配同样长的前缀时,它们的指定顺序才有意义。

由于

$us_ascii_character+

匹配整个输入,只得到一个[TokenString "From: \"John Doe\" <john@doe.org>"]

要根据需要标记输入,如果我理解正确,您需要使用像

这样的规则
\" [^\"]* \"      { \s -> TokenString s }

(免责声明:我不知道alex'的语法,实际上可能会有所不同。)