我正在尝试在Coq中编写一个程序来解析一个相对简单的无上下文语法(一种括号),而我的通用算法是让解析器可能返回字符串的其余部分。例如,解析"++]>><<"
应返回CBTerminated [Incr Incr] ">><<"
,然后说解析“[++]&gt;&gt;&lt;&lt;&lt;”能够拿起“&gt;&gt;&lt;&lt;”并继续。
很明显,字符串较小,但令人信服的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.
表示“小于”)。
我想到的是返回一个要跳过多少个字符的计数,但这看起来相当不优雅和不必要。
addView
答案 0 :(得分:8)
您是否考虑过使用well-founded recursion? Coq的标准库有一系列有用的组合器,用于定义功能良好的关系。参考1显示了一般递归的两种技术(有根据的递归和monad)。
在Agda的上下文中也非常有用的其他技术是所谓的Bove-Capretta method,它定义了一个模仿定义函数的调用图的归纳谓词。
Coq还有Function命令,可用于定义更一般的递归函数。每当我需要定义非结构递归函数时,我都使用了有根据的递归。
希望这会对你有所帮助。