【问题标题】:Why does the lexer rule for strings takes precedence over all my other rules?为什么字符串的词法分析器规则优先于我的所有其他规则?
【发布时间】:2013-06-20 21:34:53
【问题描述】:

使用 Alex 词法分析器我正在创建一个词法分析器来标记电子邮件“来自标头”。这是一个示例标题:

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 header”标记为这些标记:

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

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

这是我的 Alex 词法分析器:

{
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)

【问题讨论】:

    标签: parsing haskell lexer parser-generator alex


    【解决方案1】:

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

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

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

    自从

    $us_ascii_character+
    

    匹配整个输入,你只会得到一个[TokenString "From: \"John Doe\" &lt;john@doe.org&gt;"]

    要根据需要标记输入,如果我理解正确,您需要使用类似的规则

    \" [^\"]* \"      { \s -> TokenString s }
    

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

    【讨论】:

      猜你喜欢
      • 2023-01-03
      • 2019-05-07
      • 1970-01-01
      • 2015-04-26
      • 1970-01-01
      • 1970-01-01
      • 2020-09-14
      • 2013-04-29
      • 1970-01-01
      相关资源
      最近更新 更多