gpt4 book ai didi

haskell - 为什么这个词法分析器不解析这个输入?

转载 作者:行者123 更新时间:2023-12-04 07:45:53 26 4
gpt4 key购买 nike

我想对以下代码示例进行词法分析:

prop levelBasedAlerter uni { a b } \I -> 
levelBasedAlerter a
| a > I ->
b: "ALERT: %a"
这应该是
Prop
Var "levelBasedAlerter"
Uni
PortSpecS " { a b }"
Lam
Var "I"
PatternMatchEnd
Indent 2
Var "levelBasedAlerter"
Var "a"
Indent 4
PatternGuard
Var "a"
Var ">"
Var "I"
PatternMatchEnd
Indent 6
Var "b"
DefinedByCol
StringLit "Alert: %a"
但是,我的 alex 词法分析器在遇到 \ 时因错误而停止在第一行(在 \ 后面有和没有空格)。
为什么会这样?
词法分析器:
{
{-# LANGUAGE DeriveDataTypeable #-}
module Lexer where
import Data.Typeable
import Data.Data
import Data.List
import Data.List.Split
import Data.Char
import Debug.Trace
import Prelude hiding (lex)
import Control.Monad (liftM)
}

%wrapper "posn"

$digit = 0-9
@string = (. # [\" \\] )

$alpha = [a-zA-Z]
@real = ($digit+ \. | $digit * \. $digit +)
@boolLit = ("True"|"False")
@alphaNum = ($alpha|$digit)+
$bracketsOpen = [\(\[\{]
$bracketsClose = [\)\]\}]
$brackets = [ $bracketsOpen $bracketsClose]
@identifier = [^ : ! = \\ \ " $brackets]+
@commaOrSpace = (\,\ * | \ +)
@scopedIdentifier = @identifier(\.@identifier)+
@globalKeyword = (prop|mesh|let|omni|uni|let|using|module|import|where)
@port = (@identifier:\ *)?@identifier
@portSpec = ((@identifier|@scopedIdentifier):)?
" "*
\{\ * @port
(@commaOrSpace @port)*
" "*\}
@deepPortSpec = ((@identifier|@scopedIdentifier):)?
" "*
\{\ * @identifier: (. # \})+ \}
@indent = \n[\t\ ]+

tokens :-
@indent { \_ s -> Indent $ length s }
$white+ ;
"--".* ;
@globalKeyword { \_ keyword -> getTokenOf keyword }
$digit+ { \_ s -> IntL (read s) }
@real+ { \_ s -> DoubleL (read s) }
@boolLit { \_ s -> BoolL (read s) }
\" @string \" { \_ s -> StringLit (tail . init $ s) }
@portSpec { \_ s -> PortSpecS s }
@deepPortSpec { \_ s -> DeepPortSpecS s }
":" { \_ s -> DefinedByCol }
"," { \_ s -> Comma }
"!" { \_ s -> Negate }
"==" { \_ s -> Eq }
"=" { \_ s -> LetAssOp }
"~>" { \_ s -> Wire }
"->" { \_ s -> PatternMatchEnd }
$bracketsOpen { \_ s -> BracO s}
$bracketsClose { \_ s -> BracC s}
"||" { \_ s -> Or }
"|" { \_ s -> PatternGuard}
"!!" { \_ s -> AccessPort }
"\\" { \_ s -> Lam }

@scopedIdentifier {\_ s -> ScopedVar s }
@identifier { \_ s -> Var s }

{

clean :: String -> String
clean s = reverse $ rmWs $ reverse $ rmWs s
where rmWs = dropWhile (\c -> c ==' ' || c == '\t')

traceThis :: (Show a) => a -> a
traceThis a = trace ("DEBUG: " ++ show a) a

data Token
= Prop
| Mesh
| Module
| Import
| Where
| Var String
| BracO String
| BracC String
| Comma
| Eq
| PatternGuard
| Or
| ScopedVar String
| Omni
| Uni
| PortSpecS String
| DeepPortSpecS String
| DefinedByCol -- ':' after definitions
| Indent Int
| PatternMatchEnd -- '->' after PM
| Negate
| Let
| LetAssOp -- '=' in let x = ...
| Wire
| AccessPort
| Using
| Lam
| StringLit String
| IntL Int
| DoubleL Double
| BoolL Bool
| EOF
deriving (Eq,Show,Data)

getTokenOf :: String -> Token
getTokenOf s = fromConstr
$ head $ filter ((==s) . map toLower . showConstr)
$ dataTypeConstrs $ dataTypeOf $ Prop



}
我认为这与我如何匹配 \ 有关。 token 。
但是,我尝试过匹配它 '\' '\\' "\" "\\" \\ \还有一个正则表达式,但似乎没有任何效果。
关于 \ 是否有一些奇怪的行为?在亚历克斯?还是其他一些我看不到的小错误?
更新
我尝试更改 @identifier现在:
@identifier       = (. # [ : ! = \\ \ " $brackets])+
以 alexy 方式进行“除 x 之外的任何事情”匹配,但这并没有改变输出中的任何内容。

最佳答案

不幸的是,很难阅读您的 lex 规则。但是你的 token 定义有两个错误。
首先,以下内容:

 "\\"   {\_ s -> Lam}
应该:
  "\"   {\_ s -> Lam}
(请注意,我们不会转义反斜杠。)这确实违反直觉,但这是 Alex 规则的语法,因此您不应在此处引用反斜杠。 (否则,它将匹配两个反斜杠,背靠背。)
第二个是你的规则:
    \" @string \"  { \_ s -> StringLit (tail . init $ s) }
应该:
    \" @string* \"  { \_ s -> StringLit (tail . init $ s) }
(注意 @string 后面的星号。)也就是说,您的字符串需要接受 0 个或更多字符。
如果您进行上述两项更改,您将看到您的输入现在顺利通过。
但是,您似乎在词法分析器中尝试做的太多了:词法分析器应该非常简单;并且绝对不应该包含像 portSpec 这样复杂的规则。你有。相反,您应该简单地标记为基本成分(除字符串外或多或少由空格分隔),然后您应该使用适当的解析器生成器(如 Happy)来对您的语言进行实际解析。这是标准的方法论。

关于haskell - 为什么这个词法分析器不解析这个输入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67199771/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com