@@ -86,7 +86,30 @@ enum IntegerRepr {
8686 Bin ,
8787}
8888
89- pub fn int_token_value ( token : & LuaSyntaxToken ) -> Result < i64 , LuaParseError > {
89+ #[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
90+ pub enum IntegerOrUnsigned {
91+ Int ( i64 ) ,
92+ Uint ( u64 ) ,
93+ }
94+
95+ impl IntegerOrUnsigned {
96+ pub fn is_unsigned ( & self ) -> bool {
97+ matches ! ( self , IntegerOrUnsigned :: Uint ( _) )
98+ }
99+
100+ pub fn is_signed ( & self ) -> bool {
101+ matches ! ( self , IntegerOrUnsigned :: Int ( _) )
102+ }
103+
104+ pub fn as_integer ( & self ) -> Option < i64 > {
105+ match self {
106+ IntegerOrUnsigned :: Int ( value) => Some ( * value) ,
107+ IntegerOrUnsigned :: Uint ( _) => None ,
108+ }
109+ }
110+ }
111+
112+ pub fn int_token_value ( token : & LuaSyntaxToken ) -> Result < IntegerOrUnsigned , LuaParseError > {
90113 let text = token. text ( ) ;
91114 let repr = if text. starts_with ( "0x" ) || text. starts_with ( "0X" ) {
92115 IntegerRepr :: Hex
@@ -96,9 +119,24 @@ pub fn int_token_value(token: &LuaSyntaxToken) -> Result<i64, LuaParseError> {
96119 IntegerRepr :: Normal
97120 } ;
98121
99- let text = text. trim_end_matches ( [ 'u' , 'l' , 'U' , 'L' ] ) ;
122+ // 检查是否有无符号后缀并去除后缀
123+ let mut is_unsigned = false ;
124+ let mut suffix_count = 0 ;
125+ for c in text. chars ( ) . rev ( ) {
126+ if c == 'u' || c == 'U' {
127+ is_unsigned = true ;
128+ suffix_count += 1 ;
129+ } else if c == 'l' || c == 'L' {
130+ suffix_count += 1 ;
131+ } else {
132+ break ;
133+ }
134+ }
100135
101- let value = match repr {
136+ let text = & text[ ..text. len ( ) - suffix_count] ;
137+
138+ // 首先尝试解析为有符号整数
139+ let signed_value = match repr {
102140 IntegerRepr :: Hex => {
103141 let text = & text[ 2 ..] ;
104142 i64:: from_str_radix ( text, 16 )
@@ -109,18 +147,46 @@ pub fn int_token_value(token: &LuaSyntaxToken) -> Result<i64, LuaParseError> {
109147 }
110148 IntegerRepr :: Normal => text. parse :: < i64 > ( ) ,
111149 } ;
112- match value {
113- Ok ( value) => Ok ( value) ,
150+
151+ match signed_value {
152+ Ok ( value) => Ok ( IntegerOrUnsigned :: Int ( value) ) ,
114153 Err ( e) => {
115154 let range = token. text_range ( ) ;
116- if * e. kind ( ) == std:: num:: IntErrorKind :: PosOverflow
117- || * e. kind ( ) == std:: num:: IntErrorKind :: NegOverflow
118- {
155+
156+ // 如果是溢出错误,尝试解析为无符号整数
157+ if * e. kind ( ) == std:: num:: IntErrorKind :: PosOverflow && is_unsigned {
158+ let unsigned_value = match repr {
159+ IntegerRepr :: Hex => {
160+ let text = & text[ 2 ..] ;
161+ u64:: from_str_radix ( text, 16 )
162+ }
163+ IntegerRepr :: Bin => {
164+ let text = & text[ 2 ..] ;
165+ u64:: from_str_radix ( text, 2 )
166+ }
167+ IntegerRepr :: Normal => text. parse :: < u64 > ( ) ,
168+ } ;
169+
170+ match unsigned_value {
171+ Ok ( value) => Ok ( IntegerOrUnsigned :: Uint ( value) ) ,
172+ Err ( _) => Err ( LuaParseError :: new (
173+ LuaParseErrorKind :: SyntaxError ,
174+ & t ! (
175+ "The integer literal '%{text}' is too large to be represented" ,
176+ text = token. text( )
177+ ) ,
178+ range,
179+ ) ) ,
180+ }
181+ } else if matches ! (
182+ * e. kind( ) ,
183+ std:: num:: IntErrorKind :: NegOverflow | std:: num:: IntErrorKind :: PosOverflow
184+ ) {
119185 Err ( LuaParseError :: new (
120186 LuaParseErrorKind :: SyntaxError ,
121187 & t ! (
122188 "The integer literal '%{text}' is too large to be represented in type 'long'" ,
123- text = text
189+ text = token . text( )
124190 ) ,
125191 range,
126192 ) )
@@ -129,7 +195,7 @@ pub fn int_token_value(token: &LuaSyntaxToken) -> Result<i64, LuaParseError> {
129195 LuaParseErrorKind :: SyntaxError ,
130196 & t ! (
131197 "The integer literal '%{text}' is invalid, %{err}" ,
132- text = text,
198+ text = token . text( ) ,
133199 err = e
134200 ) ,
135201 range,
0 commit comments