@@ -46,6 +46,10 @@ Definition parse_oct_prefix : ParserAction _ := "0o".
46
46
Definition parse_dec_prefix : ParserAction _ := "".
47
47
Definition parse_hex_prefix : ParserAction _ := "0x".
48
48
49
+ (** Is [E]/[e] a valid digit in the given base? *)
50
+ Definition base_accepts_E (base : N) : bool
51
+ := (10 + N_of_ascii "E" - N_of_ascii "A" <? base)%N.
52
+
49
53
Definition parse_digits_gen_step (base : N) : ParserAction N
50
54
:= (parse_strs
51
55
(List.flat_map
@@ -81,7 +85,17 @@ Local Coercion Z.of_N : N >-> Z.
81
85
Local Coercion inject_Z : Z >-> Q.
82
86
83
87
Definition parse_num_gen (allow_neg : bool) {P} (base : N) (parse_prefix : ParserAction P) : ParserAction Q
84
- := (if allow_neg then ((strip_whitespace_around "-")?) else parse_map (fun _ => None) "")
88
+ := let parse_E_exponent
89
+ := (("e" || "E") ;;->{ fun _ v => Qpower 10 v }
90
+ (((strip_whitespace_around "-")?)
91
+ ;;->{ fun n v => if n:option _ then (-v)%Z else v }
92
+ (parse_map (digits_to_N base : _ -> Z) ((parse_digits_gen_step base)+) )))%parse in
93
+ let parse_P_exponent
94
+ := (("p" || "P") ;;->{ fun _ v => Qpower 2 v }
95
+ (((strip_whitespace_around "-")?)
96
+ ;;->{ fun n v => if n:option _ then (-v)%Z else v }
97
+ (parse_map (digits_to_N base : _ -> Z) ((parse_digits_gen_step base)+) )))%parse in
98
+ (if allow_neg then ((strip_whitespace_around "-")?) else parse_map (fun _ => None) "")
85
99
;;->{ fun n v => if n:option _ then (-v)%Q else v }
86
100
parse_prefix ;;->{ fun _ v => v }
87
101
((((parse_digits_gen_step base)* )
@@ -92,14 +106,9 @@ Definition parse_num_gen (allow_neg : bool) {P} (base : N) (parse_prefix : Parse
92
106
(parse_digits_gen_step base)* )
93
107
|| parse_map (digits_to_N base : _ -> Q) ((parse_digits_gen_step base)+))
94
108
;;->{ fun n e => match e with Some e => n * e | None => n end %Q }
95
- (((("e" || "E") ;;->{ fun _ v => Qpower 10 v }
96
- (((strip_whitespace_around "-")?)
97
- ;;->{ fun n v => if n:option _ then (-v)%Z else v }
98
- (parse_map (digits_to_N base : _ -> Z) ((parse_digits_gen_step base)+) )))
99
- || (("p" || "P") ;;->{ fun _ v => Qpower 2 v }
100
- (((strip_whitespace_around "-")?)
101
- ;;->{ fun n v => if n:option _ then (-v)%Z else v }
102
- (parse_map (digits_to_N base : _ -> Z) ((parse_digits_gen_step base)+) ))))?).
109
+ ((if base_accepts_E base
110
+ then parse_P_exponent (* if [e] is a valid character in the base, then we don't permit [e] as an exponent *)
111
+ else (parse_E_exponent || parse_P_exponent))?).
103
112
104
113
Definition parse_num (allow_neg : bool) : ParserAction Q
105
114
:= parse_num_gen allow_neg 2 parse_bin_prefix
@@ -112,6 +121,9 @@ Redirect "log" Check let ls := [("-1234", -(1234):Q); ("0xF", 15:Q); ("10.5", (1
112
121
: List.map (fun '(s, v) => ((parse_num true;;->{fun v _ => v} ε)%parse s )) ls
113
122
= List.map (fun '(s, v) => [(v, "")]) ls.
114
123
124
+ (* This was previously stack overflowing due to treating [e] as an exponent *)
125
+ Redirect "log" Compute parse_num false "0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551".
126
+
115
127
Inductive Qexpr := Qv (_ : Q) | Qeopp (a : Qexpr) | Qeadd (a b : Qexpr) | Qesub (a b : Qexpr) | Qemul (a b : Qexpr) | Qediv (a b : Qexpr) | Qepow (b e : Qexpr).
116
128
Coercion Qv : Q >-> Qexpr.
117
129
Delimit Scope Qexpr_scope with Qexpr.
0 commit comments