forked from dafny-lang/dafny
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathParsers.dfy
64 lines (57 loc) · 2.51 KB
/
Parsers.dfy
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
/*******************************************************************************
* Copyright by the contributors to the Dafny Project
* SPDX-License-Identifier: MIT
*******************************************************************************/
/**
Contains definitions of well-formedness for parsers (stating that they must consume part of their input).
*/
module Std.JSON.Utils.Parsers {
import opened BoundedInts
import opened Wrappers
import opened Views.Core
import opened Cursors
type SplitResult<+T, +R> = Result<Split<T>, CursorError<R>>
type Parser<!T, +R> = p: Parser_<T, R> | p.Valid?()
// BUG(https://github.com/dafny-lang/dafny/issues/2103)
witness ParserWitness<T, R>() // BUG(https://github.com/dafny-lang/dafny/issues/2175)
datatype Parser_<!T, +R> = Parser(fn: FreshCursor -> SplitResult<T, R>,
ghost spec: T -> bytes) {
ghost predicate Valid?() {
forall cs': FreshCursor :: fn(cs').Success? ==> fn(cs').value.StrictlySplitFrom?(cs', spec)
}
}
opaque function ParserWitness<T, R>(): (p: Parser_<T, R>)
ensures p.Valid?()
{
Parser(_ => Failure(EOF), _ => [])
}
// BUG(https://github.com/dafny-lang/dafny/issues/2137): It would be much
// nicer if `SubParser` was a special case of `Parser`, but that would require
// making `fn` in parser a partial function `-->`. The problem with that is
// that we would then have to restrict the `Valid?` clause of `Parser` on
// `fn.requires()`, thus making it unprovable in the `SubParser` case (`fn`
// for subparsers is typically a lambda, and the `requires` of lambdas are
// essentially uninformative/opaque).
datatype SubParser_<!T, +R> = SubParser(
ghost cs: Cursor,
ghost pre: FreshCursor -> bool,
fn: FreshCursor --> SplitResult<T, R>,
ghost spec: T -> bytes)
{
ghost predicate Valid?() {
&& (forall cs': FreshCursor | pre(cs') :: fn.requires(cs'))
&& (forall cs': FreshCursor | cs'.StrictlySplitFrom?(cs) :: pre(cs'))
&& (forall cs': FreshCursor | pre(cs') :: fn(cs').Success? ==> fn(cs').value.StrictlySplitFrom?(cs', spec))
}
}
type SubParser<!T, +R> = p: SubParser_<T, R> | p.Valid?()
witness SubParserWitness<T, R>() // BUG(https://github.com/dafny-lang/dafny/issues/2175)
opaque function SubParserWitness<T, R>(): (subp: SubParser_<T, R>)
ensures subp.Valid?()
{
SubParser(Cursor([], 0, 0, 0),
(cs: FreshCursor) => false,
(cs: FreshCursor) => Failure(EOF),
_ => [])
}
}