floats iter 2.2: parser accepts Tok::Float in term and pat-lit positions

This commit is contained in:
2026-05-10 15:07:39 +02:00
parent f960e39f8b
commit f62bff08a3
+27 -2
View File
@@ -162,6 +162,7 @@ fn tok_label(t: &Tok) -> String {
Tok::LParen => "`(`".into(),
Tok::RParen => "`)`".into(),
Tok::Int(v) => format!("integer `{v}`"),
Tok::Float(bits) => format!("float `0x{bits:016x}`"),
Tok::Str(s) => format!("string {s:?}"),
Tok::Ident(s) => format!("ident `{s}`"),
}
@@ -1233,6 +1234,10 @@ impl<'a> Parser<'a> {
self.cur += 1;
Ok(Term::Lit { lit: Literal::Int { value: v } })
}
Some(Token { tok: Tok::Float(bits), .. }) => {
self.cur += 1;
Ok(Term::Lit { lit: Literal::Float { bits } })
}
Some(Token { tok: Tok::Str(s), .. }) => {
self.cur += 1;
Ok(Term::Lit { lit: Literal::Str { value: s } })
@@ -1627,6 +1632,10 @@ impl<'a> Parser<'a> {
self.cur += 1;
Literal::Int { value: v }
}
Some(Token { tok: Tok::Float(bits), .. }) => {
self.cur += 1;
Literal::Float { bits }
}
Some(Token { tok: Tok::Str(s), .. }) => {
self.cur += 1;
Literal::Str { value: s }
@@ -1640,7 +1649,7 @@ impl<'a> Parser<'a> {
Literal::Bool { value: false }
} else {
return Err(ParseError::Unexpected {
expected: "literal form (integer, string, `true`, or `false`)".into(),
expected: "literal form (integer, float, string, `true`, or `false`)".into(),
got: tok_label(&Tok::Ident(s)),
pos: span.start,
});
@@ -1648,7 +1657,7 @@ impl<'a> Parser<'a> {
}
Some(t) => {
return Err(ParseError::Unexpected {
expected: "literal form (integer, string, `true`, or `false`)".into(),
expected: "literal form (integer, float, string, `true`, or `false`)".into(),
got: tok_label(&t.tok),
pos: t.span.start,
});
@@ -2403,4 +2412,20 @@ mod tests {
"expected duplicate-doc diagnostic, got: {msg}"
);
}
/// Floats milestone iter 2.2 RED: `1.5` parses as
/// `Term::Lit { lit: Literal::Float { bits: 0x3ff8_0000_0000_0000 } }`.
/// Property protected: a `Tok::Float` produced by the lexer flows through
/// `parse_term` into a `Literal::Float` AST node carrying the same bit
/// pattern, so the surface→AST translation is bit-exact.
#[test]
fn parses_float_atom_term() {
let t = parse_term("1.5").expect("parse term");
match t {
Term::Lit { lit: Literal::Float { bits } } => {
assert_eq!(bits, 0x3ff8_0000_0000_0000u64);
}
other => panic!("expected Term::Lit::Float, got {other:?}"),
}
}
}