17
17
//! Solidity type-name parsing
18
18
use lunarity_lexer:: { Lexer , Token } ;
19
19
use crate :: error:: * ;
20
- use toolshed:: Arena ;
21
20
use std:: { fmt, result} ;
22
21
23
22
#[ derive( Debug , Clone , PartialEq ) ]
@@ -32,8 +31,8 @@ pub enum Type {
32
31
Custom ( String ) ,
33
32
Array {
34
33
length : Option < u64 > ,
35
- inner : Box < Type >
36
- }
34
+ inner : Box < Type > ,
35
+ } ,
37
36
}
38
37
39
38
impl From < Type > for String {
@@ -68,81 +67,70 @@ impl fmt::Display for Type {
68
67
}
69
68
}
70
69
71
- pub struct Parser {
72
- arena : Arena ,
73
- }
74
70
75
- impl Parser {
76
- pub fn new ( ) -> Self {
77
- Parser {
78
- arena : Arena :: new ( )
79
- }
80
- }
81
-
82
- /// the type string is being validated before it's parsed.
83
- pub fn parse_type ( & self , field_type : & str ) -> Result < Type > {
84
- #[ derive( PartialEq ) ]
85
- enum State { Open , Close }
86
-
87
- let mut lexer = Lexer :: new ( & self . arena , field_type) ;
88
- let mut token = None ;
89
- let mut state = State :: Close ;
90
- let mut array_depth = 0 ;
91
- let mut current_array_length: Option < u64 > = None ;
92
-
93
- while lexer. token != Token :: EndOfProgram {
94
- let type_ = match lexer. token {
95
- Token :: Identifier => Type :: Custom ( lexer. token_as_str ( ) . to_owned ( ) ) ,
96
- Token :: TypeByte => Type :: Byte ( lexer. type_size . 0 ) ,
97
- Token :: TypeBytes => Type :: Bytes ,
98
- Token :: TypeBool => Type :: Bool ,
99
- Token :: TypeUint => Type :: Uint ,
100
- Token :: TypeInt => Type :: Int ,
101
- Token :: TypeString => Type :: String ,
102
- Token :: TypeAddress => Type :: Address ,
103
- Token :: LiteralInteger => {
104
- let length = lexer. token_as_str ( ) ;
105
- current_array_length = Some ( length
106
- . parse ( )
107
- . map_err ( |_|
108
- ErrorKind :: InvalidArraySize ( length. into ( ) )
109
- ) ?
110
- ) ;
111
- lexer. consume ( ) ;
71
+ /// the type string is being validated before it's parsed.
72
+ pub fn parse_type ( field_type : & str ) -> Result < Type > {
73
+ #[ derive( PartialEq ) ]
74
+ enum State { Open , Close }
75
+
76
+ let mut lexer = Lexer :: new ( field_type) ;
77
+ let mut token = None ;
78
+ let mut state = State :: Close ;
79
+ let mut array_depth = 0 ;
80
+ let mut current_array_length: Option < u64 > = None ;
81
+
82
+ while lexer. token != Token :: EndOfProgram {
83
+ let type_ = match lexer. token {
84
+ Token :: Identifier => Type :: Custom ( lexer. slice ( ) . to_owned ( ) ) ,
85
+ Token :: TypeByte => Type :: Byte ( lexer. extras . 0 ) ,
86
+ Token :: TypeBytes => Type :: Bytes ,
87
+ Token :: TypeBool => Type :: Bool ,
88
+ Token :: TypeUint => Type :: Uint ,
89
+ Token :: TypeInt => Type :: Int ,
90
+ Token :: TypeString => Type :: String ,
91
+ Token :: TypeAddress => Type :: Address ,
92
+ Token :: LiteralInteger => {
93
+ let length = lexer. slice ( ) ;
94
+ current_array_length = Some ( length
95
+ . parse ( )
96
+ . map_err ( |_|
97
+ ErrorKind :: InvalidArraySize ( length. into ( ) )
98
+ ) ?
99
+ ) ;
100
+ lexer. advance ( ) ;
101
+ continue ;
102
+ }
103
+ Token :: BracketOpen if token. is_some ( ) && state == State :: Close => {
104
+ state = State :: Open ;
105
+ lexer. advance ( ) ;
106
+ continue ;
107
+ }
108
+ Token :: BracketClose if array_depth < 10 => {
109
+ if state == State :: Open && token. is_some ( ) {
110
+ let length = current_array_length. take ( ) ;
111
+ state = State :: Close ;
112
+ token = Some ( Type :: Array {
113
+ inner : Box :: new ( token. expect ( "if statement checks for some; qed" ) ) ,
114
+ length,
115
+ } ) ;
116
+ lexer. advance ( ) ;
117
+ array_depth += 1 ;
112
118
continue ;
113
- } ,
114
- Token :: BracketOpen if token. is_some ( ) && state == State :: Close => {
115
- state = State :: Open ;
116
- lexer. consume ( ) ;
117
- continue
119
+ } else {
120
+ return Err ( ErrorKind :: UnexpectedToken ( lexer. slice ( ) . to_owned ( ) , field_type. to_owned ( ) ) ) ?;
118
121
}
119
- Token :: BracketClose if array_depth < 10 => {
120
- if state == State :: Open && token. is_some ( ) {
121
- let length = current_array_length. take ( ) ;
122
- state = State :: Close ;
123
- token = Some ( Type :: Array {
124
- inner : Box :: new ( token. expect ( "if statement checks for some; qed" ) ) ,
125
- length
126
- } ) ;
127
- lexer. consume ( ) ;
128
- array_depth += 1 ;
129
- continue
130
- } else {
131
- return Err ( ErrorKind :: UnexpectedToken ( lexer. token_as_str ( ) . to_owned ( ) , field_type. to_owned ( ) ) ) ?
132
- }
133
- }
134
- Token :: BracketClose if array_depth == 10 => {
135
- return Err ( ErrorKind :: UnsupportedArrayDepth ) ?
136
- }
137
- _ => return Err ( ErrorKind :: UnexpectedToken ( lexer. token_as_str ( ) . to_owned ( ) , field_type. to_owned ( ) ) ) ?
138
- } ;
139
-
140
- token = Some ( type_) ;
141
- lexer. consume ( ) ;
142
- }
122
+ }
123
+ Token :: BracketClose if array_depth == 10 => {
124
+ return Err ( ErrorKind :: UnsupportedArrayDepth ) ?;
125
+ }
126
+ _ => return Err ( ErrorKind :: UnexpectedToken ( lexer. slice ( ) . to_owned ( ) , field_type. to_owned ( ) ) ) ?
127
+ } ;
143
128
144
- Ok ( token. ok_or_else ( || ErrorKind :: NonExistentType ) ?)
129
+ token = Some ( type_) ;
130
+ lexer. advance ( ) ;
145
131
}
132
+
133
+ Ok ( token. ok_or_else ( || ErrorKind :: NonExistentType ) ?)
146
134
}
147
135
148
136
#[ cfg( test) ]
@@ -151,22 +139,19 @@ mod tests {
151
139
152
140
#[ test]
153
141
fn test_parser ( ) {
154
- let parser = Parser :: new ( ) ;
155
142
let source = "byte[][][7][][][][][][][]" ;
156
- parser . parse_type ( source) . unwrap ( ) ;
143
+ parse_type ( source) . unwrap ( ) ;
157
144
}
158
145
159
146
#[ test]
160
147
fn test_nested_array ( ) {
161
- let parser = Parser :: new ( ) ;
162
148
let source = "byte[][][7][][][][][][][][]" ;
163
- assert_eq ! ( parser . parse_type( source) . is_err( ) , true ) ;
149
+ assert_eq ! ( parse_type( source) . is_err( ) , true ) ;
164
150
}
165
151
166
152
#[ test]
167
153
fn test_malformed_array_type ( ) {
168
- let parser = Parser :: new ( ) ;
169
154
let source = "byte[7[]uint][]" ;
170
- assert_eq ! ( parser . parse_type( source) . is_err( ) , true )
155
+ assert_eq ! ( parse_type( source) . is_err( ) , true )
171
156
}
172
157
}
0 commit comments