@@ -86,7 +86,30 @@ enum IntegerRepr {
86
86
Bin ,
87
87
}
88
88
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 > {
90
113
let text = token. text ( ) ;
91
114
let repr = if text. starts_with ( "0x" ) || text. starts_with ( "0X" ) {
92
115
IntegerRepr :: Hex
@@ -96,9 +119,24 @@ pub fn int_token_value(token: &LuaSyntaxToken) -> Result<i64, LuaParseError> {
96
119
IntegerRepr :: Normal
97
120
} ;
98
121
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
+ }
100
135
101
- let value = match repr {
136
+ let text = & text[ ..text. len ( ) - suffix_count] ;
137
+
138
+ // 首先尝试解析为有符号整数
139
+ let signed_value = match repr {
102
140
IntegerRepr :: Hex => {
103
141
let text = & text[ 2 ..] ;
104
142
i64:: from_str_radix ( text, 16 )
@@ -109,18 +147,46 @@ pub fn int_token_value(token: &LuaSyntaxToken) -> Result<i64, LuaParseError> {
109
147
}
110
148
IntegerRepr :: Normal => text. parse :: < i64 > ( ) ,
111
149
} ;
112
- match value {
113
- Ok ( value) => Ok ( value) ,
150
+
151
+ match signed_value {
152
+ Ok ( value) => Ok ( IntegerOrUnsigned :: Int ( value) ) ,
114
153
Err ( e) => {
115
154
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
+ ) {
119
185
Err ( LuaParseError :: new (
120
186
LuaParseErrorKind :: SyntaxError ,
121
187
& t ! (
122
188
"The integer literal '%{text}' is too large to be represented in type 'long'" ,
123
- text = text
189
+ text = token . text( )
124
190
) ,
125
191
range,
126
192
) )
@@ -129,7 +195,7 @@ pub fn int_token_value(token: &LuaSyntaxToken) -> Result<i64, LuaParseError> {
129
195
LuaParseErrorKind :: SyntaxError ,
130
196
& t ! (
131
197
"The integer literal '%{text}' is invalid, %{err}" ,
132
- text = text,
198
+ text = token . text( ) ,
133
199
err = e
134
200
) ,
135
201
range,
0 commit comments