【问题标题】:How do I match a Regular Expression in a Happy parser?如何匹配快乐解析器中的正则表达式?
【发布时间】:2012-02-14 02:07:13
【问题描述】:

我正在用Happy 编写一个JavaScript 解析器,我需要匹配一个正则表达式。我不想完全解析正则表达式,只需将其存储为字符串即可。

我的 AST 的相关部分如下所示:

data PrimaryExpr
    -- | Literal integer
    = ExpLitInt     Integer
    -- | Literal strings
    | ExpLitStr     String
    -- | Identifier
    | ExpId         String
    -- | Bracketed expression
    | ExpBrackExp   Expression
    -- | This (current object)
    | ExpThis
    -- | Regular Expression
    | ExpRegex      String
    -- | Arrays
    | ExpArray      ArrayLit
    -- | Objects
    | ExpObject     [(PropName, Assignment)]
    deriving Show

这是相关的快乐代码:

primaryExpr :: { PrimaryExpr }
    : LITINT          { ExpLitInt $1 }
    | LITSTR          { ExpLitStr $1 }
    | ID              { ExpId $1 }
    | THIS            { ExpThis }
    | regex           { ExpRegex $1 }
    | arrayLit        { ExpArray $1 }
    | objectLit       { ExpObject $1 }
    | '(' expression ')' { ExpBrackExp $2 }

我的问题是,我应该如何定义我的 regex 非终端?这种结构对吗?

regex :: { String }
    : '/' whatHere? '/' { $2 }

【问题讨论】:

    标签: javascript parsing haskell parser-generator happy


    【解决方案1】:

    您应该将正则表达式定义为词法分析器识别的终端(即 LITREGEX)。

    primaryExpr :: { PrimaryExpr }
        : LITINT          { ExpLitInt $1 }
        | LITSTR          { ExpLitStr $1 }
        | LITREGEX        { ExpRegex $1 }
        | ID              { ExpId $1 }
        | THIS            { ExpThis }
        | arrayLit        { ExpArray $1 }
        | objectLit       { ExpObject $1 }
        | '(' expression ')' { ExpBrackExp $2 }
    

    【讨论】:

    • 好的,好主意。这就引出了下一个问题——如何让 Alex 词法分析器匹配正则表达式? (如果您认为这是一个更好的主意,我可以将其作为一个单独的问题提出?)
    • 我不是 Alex 专家,但类似于 \/[^\/]*\/ { \s -> LITREGEX . init . tail $ s }。这不允许在正则表达式中转义 /。 YMMV
    • 要正确执行此操作,您需要处理反斜杠转义的 / 和 / 内部字符类。
    • 是的,这就是我要解决的问题。但除此之外它是完美的。它匹配简单的正则表达式,而不是带有转义正斜杠的正则表达式。我会努力的,谢谢!
    • 最终解决方案:\/([^\/]|\\\/)*\/[gim]* { \s -> Regex s }
    【解决方案2】:

    要回答评论中的问题,需要更多空间。

    类似的东西(隔开并注释):

    /             forward slash
    (  \\.        either: an escaped character
    |  [^\[/\\]           anything which isn't / or [ or \
    |  \[                 a character class containing:
         [^\]]*              anything which isn't ] any number of times
       \]                   
    )*            any number of times
    /             forward slash
    

    精简:

    /(\\.|[^\[/\\]|\[[^\]]*\])*/
    

    【讨论】:

    • 这太棒了,干杯。反正我觉得比我的好。我不得不转义正斜杠并添加修饰符,所以这是最终产品:\/(\\.|[^\[\/]|\[[^\]]*\])*\/[gim]* { \s -> Regex s }
    • 我想说我不知道​​你需要什么来逃避快乐,但你似乎已经想通了 :)
    • 字符类允许第一个字符是 ] 而不会关闭类
    • @pat:有时。不在 Javascript 中。我最近被这个咬了:) 它在 Chrome 中:i.imgur.com/UFtKt.png
    • @pat: PCRE 和 PCRE 兼容的东西允许它。他们还允许[^]] :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多