f# - 获取一条指令抛出的最后一条错误消息
问题描述
我注意到 FParsec 发送的错误消息非常“模棱两可”,除了为指令发送的最后一条消息。这是一个例子:
要解析的代码:
if (2 + 2 == 4)
在这里,通常应该有一个指令块(所以在括号中)。
我得到了什么:
失败:Ln 中的错误:1 Col:1 if (2 + 2 == 4) ^ 期望:[一些说明]
解析器在以下之后回溯:Ln 中的错误:1 Col:3 if (2 + 2 == 4) ^ Bad identifier: 'if' is a reserved keyword
解析器回溯后:Ln 中的错误:1 Col:16 if (2 + 2 == 4) ^ 注意:错误发生在输入流的末尾。期望:开始块
如您所见,只有最后一条错误消息是相关的。所以我想知道是否没有办法只显示这个,因此最后一个而不经过其他。我想这并不容易,因为它是 FParsec 的一个功能,但你永远不知道......
我认为我不需要发布 F# 代码,因为它通常是在使用库时。
编辑
这是我的分析器解析上述示例的代码:
type Statement =
| If of Expr * Block option
// And others...
and Block = Block of Statement list
let ws = pspaces >>. many pspaces |>> (fun _ -> ())
let str_ws s = pstring s .>> ws
let pexpr, pexprimpl = createParserForwardedToRef ()
// With their implementations (addition, subtraction, ...)
let pstatement, pstatementimpl = createParserForwardedToRef ()
// With their implementations, like "pif" below
let psinglestatement = pstatement |>> fun statement -> [statement]
let pstatementblock =
psinglestatement <|>
between (ws >>. str_ws "{") (ws >>. str_ws "}") (many pstatement)
let pif =
pipe2
(str_ws "if" >>. pexpr)
(pstatementblock)
(fun cnd block -> If(cnd, Some (Block(block))))
pstatementimpl :=
attempt (pif) <|>
// And others...
编辑二:
下面是标识符分析的代码:
let reserved = [
"if"; "else" // And other...
]
let pidentifierraw =
let inline isIdentifierFirstChar c = isLetter c
let inline isIdentifierChar c = isLetter c || isDigit c
many1Satisfy2L isIdentifierFirstChar isIdentifierChar "identifier"
let pidentifier =
pidentifierraw
>>= fun s ->
if reserved |> List.exists ((=) s) then fail ("Bad identifier: '" + s + "' is a reserved keyword")
else preturn s
type Literal =
| Identifier of string
// And other...
let pid = pidentifier |>> Literal.Identifier
pexpr
是一组值,包括标识符、文字及其操作:
let pexpr, pexprimpl = createParserForwardedToRef ()
type Assoc = Associativity
let opp = OperatorPrecedenceParser<Expr, unit, unit> ()
pexprimpl := opp.ExpressionParser <?> "expression"
let term = pvalue .>> ws <|> between (str_ws "(") (str_ws ")") pexpr
opp.TermParser <- term
let inops = [ "+"; "-"; "*"; "/"; "=="; "!="; "<="; ">="; "<"; ">" ]
for op in inops do opp.AddOperator(InfixOperator(op, ws, 1, Assoc.Left, fun x y -> InfixOp(x, op, y)))
pvalue
定义文字,包括带有pidentifier
. 我不认为我需要把他们的定义,因为他们都遵循这种模式(例如):
let ptrue = str_ws "true" |>> fun _ -> Bool(true)
let pfalse = str_ws "false" |>> fun _ -> Bool(false)
let pbool = ptrue <|> pfalse
解决方案
推荐阅读
- java - 我在发送屏幕截图时遇到错误
- java - 使用扫描仪读取“干净”文本文件时是否有任何解析?
- c# - 本地驱动器上的 UWP SharpCompress 访问异常,为什么?
- laravel-7 - 登录过期后laravel aws serverless 419
- kotlin - 在 kotlin 中获得最少两个或多个整数的最快方法是什么?
- reactjs - 无法理解 React 'unmounted' 组件定义
- hibernate - JAX-RS 中的 LazyInitializationException 和 DTO
- r - 我可以在 R Markdown HTML flextable 的正文中包含公式吗
- django - 异常类型:NameError at / 异常值:名称 'pcgames' 未在 django 中定义
- solr - Solr Regex 基于设置条件的查询的未知部分