【发布时间】:2016-05-26 23:34:26
【问题描述】:
我正在尝试在 Coq 中编写一个程序来解析一个相对简单的上下文无关语法(一种括号),我的一般算法是让解析器可能返回字符串的其余部分。例如,解析"++]>><<" 应该返回CBTerminated [Incr Incr] ">><<",然后说解析“[++]>>>
很明显,字符串更小了,但说服 Coq 是另一回事。它给了我错误
parseHelper 的递归定义格式不正确。 [...] 对 parseHelper 的递归调用的主要参数等于“rest” “休息”。
我假设这意味着它不相信rest' < input,就像它相信rest < input一样。 (其中< 表示“小于”)。
我曾想过返回一个要跳过多少字符的计数,但这似乎相当不雅和不必要。
Require Import Coq.Strings.String.
Require Import Coq.Strings.Ascii.
Require Import Coq.Lists.List.
Require Import ZArith.
Open Scope char_scope.
Open Scope list_scope.
Notation " [ ] " := nil (format "[ ]") : list_scope.
Notation " [ x ] " := (cons x nil) : list_scope.
Notation " [ x ; y ; .. ; z ] " := (cons x (cons y .. (cons z nil) ..)) : list_scope.
Inductive BF :=
| Incr : BF
| Decr : BF
| Left : BF
| Right : BF
| In : BF
| Out : BF
| Sequence : list BF -> BF
| While : BF -> BF.
Inductive BF_Parse_Result :=
| UnmatchedOpen
| EOFTerminated (u : list BF)
| CBTerminated (u : list BF) (rest : string).
Definition bind (val : BF) (onto : BF_Parse_Result) :=
match onto with
| UnmatchedOpen => UnmatchedOpen
| EOFTerminated values => EOFTerminated (cons val values)
| CBTerminated values rest => CBTerminated (cons val values) rest
end.
Fixpoint parseHelper (input : string) : BF_Parse_Result :=
match input with
| EmptyString => EOFTerminated nil
| String first rest =>
match first with
| "+" => bind Incr (parseHelper rest)
| "-" => bind Decr (parseHelper rest)
| "<" => bind Left (parseHelper rest)
| ">" => bind Right (parseHelper rest)
| "," => bind In (parseHelper rest)
| "." => bind Out (parseHelper rest)
| "]" => CBTerminated nil rest
| "[" =>
match parseHelper rest with
| UnmatchedOpen => UnmatchedOpen
| EOFTerminated _ => UnmatchedOpen
| CBTerminated vals rest' =>
bind (While (Sequence vals)) (parseHelper rest')
end
| _ => parseHelper rest
end
end.
【问题讨论】:
-
嗯,这通常很棘手。作为第一次尝试,我建议您通过调用次数的递归来定义您的函数。也就是加一个nat参数,限制函数调用的次数。但是
parseHelper (length input) input是正确的。一旦你的表单工作起来,你就可以开始重构(也许使用累加器?)见:x80.org/collacoq/abidadadol.coq -
@ejgallego 我试过了,但发现很难证明
parseHelper (length input) input实际上是正确的。 -
嗯,这应该不会比证明您发布的版本正确更难,它会被 Coq 接受。您可能需要一个引理来说明解析结果对于大于
lenght input的大小是相同的,或者切换到返回一些大小以获得精确值,但您不希望这样。 -
是的,特别是对于给定的定义,您需要将正确性引理推广到
forall n, length input <= n, "correct" parseHelper n input以获得可用的归纳假设。
标签: recursion coq termination