如何调整Racket parser-tools/lex的字符串词法规则实现正确匹配?
Racket词法分析器字符串匹配问题解决
我在用Racket的parser-tools/lex和parser-tools/lex-sre编写词法分析器,目标是为字符串生成对应的Token,但当前匹配逻辑存在问题:当遇到"this is" .... "cool"这类内容时,会被识别为单个Token,而非预期的StringToken、中间Tokens、StringToken形式。
我当前使用的词法规则如下:
[ (: #\" (repetition 0 +inf.0 (complement (or #\newline whitespace ) ) ) #\") (begin (token-STRING lexeme )) ]
你的问题根源在于当前规则的匹配范围过宽且采用贪婪匹配,导致它会从第一个"一直匹配到最后一个",把中间所有内容都纳入单个Token。要解决这个问题,核心是让字符串匹配在遇到下一个"时立即停止,而非跳过它继续匹配。
调整后的基础规则
把字符串内容的匹配逻辑改为:仅排除双引号和换行符(如果你的语言允许字符串跨行,可去掉换行符限制),而非排除空白字符。修改后的规则如下:
[ (: #\" (repetition 0 +inf.0 (complement (or #\" #\newline)) ; 仅排除双引号和换行符 ) #\") (begin (token-STRING lexeme)) ]
调整逻辑说明
- 原规则排除的是换行符和空白字符,这意味着除这两类字符外的所有内容(包括中间的
")都会被匹配,自然会把多个字符串连起来识别。 - 修改后的规则只限制双引号和换行符,匹配到下一个
"就会终止,每个被"包裹的部分都会被单独识别为StringToken,中间内容则会交给其他词法规则处理。
额外补充:支持转义双引号的场景
如果你的语言需要支持转义双引号(比如"this is \"cool\" string"),还需要额外处理转义字符,避免转义的"被误判为字符串结束符。此时规则需调整为:
[ (: #\" (repetition 0 +inf.0 (or (: #\\ any-char) ; 匹配转义字符及后续任意字符 (complement (or #\" #\newline)) ) ) #\") (begin (token-STRING lexeme)) ]
内容的提问来源于stack exchange,提问作者IDANG
相关产品推荐
相关产品推荐

