@@ -36,20 +36,32 @@ pub enum LitError {
3636 InvalidSuffix ( Symbol ) ,
3737 InvalidIntSuffix ( Symbol ) ,
3838 InvalidFloatSuffix ( Symbol ) ,
39+ InvalidNegation ( token:: LitKind ) ,
3940 NonDecimalFloat ( u32 ) , // u32 is the base
4041 IntTooLarge ( u32 ) , // u32 is the base
4142}
4243
4344impl LitKind {
44- /// Converts literal token into a semantic literal.
4545 pub fn from_token_lit ( lit : token:: Lit ) -> Result < LitKind , LitError > {
46+ Self :: from_token_lit_maybe_negated ( lit, false )
47+ }
48+
49+ /// Converts literal token into a semantic literal.
50+ pub fn from_token_lit_maybe_negated (
51+ lit : token:: Lit ,
52+ negated : bool ,
53+ ) -> Result < LitKind , LitError > {
4654 let token:: Lit { kind, symbol, suffix } = lit;
4755 if let Some ( suffix) = suffix
4856 && !kind. may_have_suffix ( )
4957 {
5058 return Err ( LitError :: InvalidSuffix ( suffix) ) ;
5159 }
5260
61+ if negated && !matches ! ( kind, token:: Integer | token:: Float ) {
62+ return Err ( LitError :: InvalidNegation ( kind) ) ;
63+ }
64+
5365 // For byte/char/string literals, chars and escapes have already been
5466 // checked in the lexer (in `cook_lexer_literal`). So we can assume all
5567 // chars and escapes are valid here.
@@ -71,8 +83,8 @@ impl LitKind {
7183
7284 // There are some valid suffixes for integer and float literals,
7385 // so all the handling is done internally.
74- token:: Integer => return integer_lit ( symbol, suffix) ,
75- token:: Float => return float_lit ( symbol, suffix) ,
86+ token:: Integer => return integer_lit ( symbol, suffix, negated ) ,
87+ token:: Float => return float_lit ( symbol, suffix, negated ) ,
7688
7789 token:: Str => {
7890 // If there are no characters requiring special treatment we can
@@ -189,14 +201,21 @@ impl fmt::Display for LitKind {
189201 let symbol = str:: from_utf8 ( bytes) . unwrap ( ) ;
190202 write ! ( f, "cr{delim}\" {symbol}\" {delim}" , delim = "#" . repeat( n as usize ) , ) ?;
191203 }
192- LitKind :: Int ( n, ty) => {
193- write ! ( f, "{n}" ) ?;
194- match ty {
195- ast:: LitIntType :: Unsigned ( ty) => write ! ( f, "{}" , ty. name( ) ) ?,
196- ast:: LitIntType :: Signed ( ty) => write ! ( f, "{}" , ty. name( ) ) ?,
197- ast:: LitIntType :: Unsuffixed => { }
204+ LitKind :: Int ( n, ty) => match ty {
205+ ast:: LitIntType :: Unsigned ( ty) => write ! ( f, "{n}{}" , ty. name( ) ) ?,
206+ ast:: LitIntType :: Signed ( ty, negated) => {
207+ if negated {
208+ write ! ( f, "-" ) ?;
209+ }
210+ write ! ( f, "{n}{}" , ty. name( ) ) ?
198211 }
199- }
212+ ast:: LitIntType :: Unsuffixed ( negated) => {
213+ if negated {
214+ write ! ( f, "-" ) ?;
215+ }
216+ write ! ( f, "{n}" ) ?;
217+ }
218+ } ,
200219 LitKind :: Float ( symbol, ty) => {
201220 write ! ( f, "{symbol}" ) ?;
202221 match ty {
@@ -269,11 +288,13 @@ fn filtered_float_lit(
269288 symbol : Symbol ,
270289 suffix : Option < Symbol > ,
271290 base : u32 ,
291+ negated : bool ,
272292) -> Result < LitKind , LitError > {
273- debug ! ( "filtered_float_lit: {:?}, {:?}, {:?}" , symbol , suffix , base ) ;
293+ debug ! ( ?symbol , ?suffix , ?base , ?negated ) ;
274294 if base != 10 {
275295 return Err ( LitError :: NonDecimalFloat ( base) ) ;
276296 }
297+ let symbol = if negated { Symbol :: intern ( & format ! ( "-{}" , symbol. as_str( ) ) ) } else { symbol } ;
277298 Ok ( match suffix {
278299 Some ( suffix) => LitKind :: Float (
279300 symbol,
@@ -289,12 +310,12 @@ fn filtered_float_lit(
289310 } )
290311}
291312
292- fn float_lit ( symbol : Symbol , suffix : Option < Symbol > ) -> Result < LitKind , LitError > {
313+ fn float_lit ( symbol : Symbol , suffix : Option < Symbol > , negated : bool ) -> Result < LitKind , LitError > {
293314 debug ! ( "float_lit: {:?}, {:?}" , symbol, suffix) ;
294- filtered_float_lit ( strip_underscores ( symbol) , suffix, 10 )
315+ filtered_float_lit ( strip_underscores ( symbol) , suffix, 10 , negated )
295316}
296317
297- fn integer_lit ( symbol : Symbol , suffix : Option < Symbol > ) -> Result < LitKind , LitError > {
318+ fn integer_lit ( symbol : Symbol , suffix : Option < Symbol > , negated : bool ) -> Result < LitKind , LitError > {
298319 debug ! ( "integer_lit: {:?}, {:?}" , symbol, suffix) ;
299320 let symbol = strip_underscores ( symbol) ;
300321 let s = symbol. as_str ( ) ;
@@ -308,12 +329,12 @@ fn integer_lit(symbol: Symbol, suffix: Option<Symbol>) -> Result<LitKind, LitErr
308329
309330 let ty = match suffix {
310331 Some ( suf) => match suf {
311- sym:: isize => ast:: LitIntType :: Signed ( ast:: IntTy :: Isize ) ,
312- sym:: i8 => ast:: LitIntType :: Signed ( ast:: IntTy :: I8 ) ,
313- sym:: i16 => ast:: LitIntType :: Signed ( ast:: IntTy :: I16 ) ,
314- sym:: i32 => ast:: LitIntType :: Signed ( ast:: IntTy :: I32 ) ,
315- sym:: i64 => ast:: LitIntType :: Signed ( ast:: IntTy :: I64 ) ,
316- sym:: i128 => ast:: LitIntType :: Signed ( ast:: IntTy :: I128 ) ,
332+ sym:: isize => ast:: LitIntType :: Signed ( ast:: IntTy :: Isize , negated ) ,
333+ sym:: i8 => ast:: LitIntType :: Signed ( ast:: IntTy :: I8 , negated ) ,
334+ sym:: i16 => ast:: LitIntType :: Signed ( ast:: IntTy :: I16 , negated ) ,
335+ sym:: i32 => ast:: LitIntType :: Signed ( ast:: IntTy :: I32 , negated ) ,
336+ sym:: i64 => ast:: LitIntType :: Signed ( ast:: IntTy :: I64 , negated ) ,
337+ sym:: i128 => ast:: LitIntType :: Signed ( ast:: IntTy :: I128 , negated ) ,
317338 sym:: usize => ast:: LitIntType :: Unsigned ( ast:: UintTy :: Usize ) ,
318339 sym:: u8 => ast:: LitIntType :: Unsigned ( ast:: UintTy :: U8 ) ,
319340 sym:: u16 => ast:: LitIntType :: Unsigned ( ast:: UintTy :: U16 ) ,
@@ -322,11 +343,18 @@ fn integer_lit(symbol: Symbol, suffix: Option<Symbol>) -> Result<LitKind, LitErr
322343 sym:: u128 => ast:: LitIntType :: Unsigned ( ast:: UintTy :: U128 ) ,
323344 // `1f64` and `2f32` etc. are valid float literals, and
324345 // `fxxx` looks more like an invalid float literal than invalid integer literal.
325- _ if suf. as_str ( ) . starts_with ( 'f' ) => return filtered_float_lit ( symbol, suffix, base) ,
346+ _ if suf. as_str ( ) . starts_with ( 'f' ) => {
347+ return filtered_float_lit ( symbol, suffix, base, negated) ;
348+ }
326349 _ => return Err ( LitError :: InvalidIntSuffix ( suf) ) ,
327350 } ,
328- _ => ast:: LitIntType :: Unsuffixed ,
351+ _ => ast:: LitIntType :: Unsuffixed ( negated ) ,
329352 } ;
353+ if let ast:: LitIntType :: Unsigned ( _) = ty
354+ && negated
355+ {
356+ return Err ( LitError :: InvalidNegation ( token:: Integer ) ) ;
357+ }
330358
331359 let s = & s[ if base != 10 { 2 } else { 0 } ..] ;
332360 u128:: from_str_radix ( s, base)
0 commit comments