1use crate::{
2 kw, utils::ParseNested, Lit, LitDenominated, SolIdent, Spanned, SubDenomination, Type,
3};
4use proc_macro2::{Ident, Span};
5use std::fmt;
6use syn::{
7 ext::IdentExt,
8 parse::{Parse, ParseStream},
9 token::{Brace, Bracket, Paren},
10 Result, Token,
11};
12
13mod array;
14pub use array::{ExprArray, ExprIndex};
15
16mod args;
17pub use args::{
18 ArgList, ArgListImpl, ExprCall, ExprCallOptions, ExprPayable, NamedArg, NamedArgList,
19};
20
21mod binary;
22pub use binary::{BinOp, ExprBinary};
23
24mod member;
25pub use member::ExprMember;
26
27mod ternary;
28pub use ternary::ExprTernary;
29
30mod tuple;
31pub use tuple::ExprTuple;
32
33mod r#type;
34pub use r#type::{ExprNew, ExprTypeCall};
35
36mod unary;
37pub use unary::{ExprDelete, ExprPostfix, ExprUnary, PostUnOp, UnOp};
38
39#[derive(Clone)]
44pub enum Expr {
45 Array(ExprArray),
47
48 Binary(ExprBinary),
50
51 Call(ExprCall),
53
54 CallOptions(ExprCallOptions),
56
57 Delete(ExprDelete),
59
60 Ident(SolIdent),
62
63 Index(ExprIndex),
65
66 Lit(Lit),
68
69 LitDenominated(LitDenominated),
71
72 Member(ExprMember),
74
75 New(ExprNew),
77
78 Payable(ExprPayable),
80
81 Postfix(ExprPostfix),
83
84 Ternary(ExprTernary),
86
87 Tuple(ExprTuple),
89
90 Type(Type),
94
95 TypeCall(ExprTypeCall),
97
98 Unary(ExprUnary),
100}
101
102impl fmt::Debug for Expr {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 f.write_str("Expr::")?;
105 match self {
106 Self::Array(expr) => expr.fmt(f),
107 Self::Binary(expr) => expr.fmt(f),
108 Self::Call(expr) => expr.fmt(f),
109 Self::CallOptions(expr) => expr.fmt(f),
110 Self::Delete(expr) => expr.fmt(f),
111 Self::Ident(ident) => ident.fmt(f),
112 Self::Index(expr) => expr.fmt(f),
113 Self::Lit(lit) => lit.fmt(f),
114 Self::LitDenominated(lit) => lit.fmt(f),
115 Self::Member(expr) => expr.fmt(f),
116 Self::New(expr) => expr.fmt(f),
117 Self::Payable(expr) => expr.fmt(f),
118 Self::Postfix(expr) => expr.fmt(f),
119 Self::Ternary(expr) => expr.fmt(f),
120 Self::Tuple(expr) => expr.fmt(f),
121 Self::Type(ty) => ty.fmt(f),
122 Self::TypeCall(expr) => expr.fmt(f),
123 Self::Unary(expr) => expr.fmt(f),
124 }
125 }
126}
127
128impl Parse for Expr {
129 fn parse(input: ParseStream<'_>) -> Result<Self> {
130 let _ = input.call(syn::Attribute::parse_outer)?;
132
133 debug!(" > Expr: {:?}", input.to_string());
134 let mut expr = Self::parse_simple(input)?;
135 debug!(" < Expr: {expr:?}");
136 loop {
137 let (new, cont) = Self::parse_nested(expr, input)?;
138 if cont {
139 debug!(" << Expr: {new:?}");
140 expr = new;
141 } else {
142 return Ok(new);
143 }
144 }
145 }
146}
147
148impl Spanned for Expr {
149 fn span(&self) -> Span {
150 match self {
151 Self::Array(expr) => expr.span(),
152 Self::Binary(expr) => expr.span(),
153 Self::Call(expr) => expr.span(),
154 Self::CallOptions(expr) => expr.span(),
155 Self::Delete(expr) => expr.span(),
156 Self::Ident(ident) => ident.span(),
157 Self::Index(expr) => expr.span(),
158 Self::Lit(lit) => lit.span(),
159 Self::LitDenominated(lit) => lit.span(),
160 Self::Member(expr) => expr.span(),
161 Self::New(expr) => expr.span(),
162 Self::Payable(expr) => expr.span(),
163 Self::Postfix(expr) => expr.span(),
164 Self::Ternary(expr) => expr.span(),
165 Self::Tuple(expr) => expr.span(),
166 Self::Type(ty) => ty.span(),
167 Self::TypeCall(expr) => expr.span(),
168 Self::Unary(expr) => expr.span(),
169 }
170 }
171
172 fn set_span(&mut self, span: Span) {
173 match self {
174 Self::Array(expr) => expr.set_span(span),
175 Self::Binary(expr) => expr.set_span(span),
176 Self::Call(expr) => expr.set_span(span),
177 Self::CallOptions(expr) => expr.set_span(span),
178 Self::Delete(expr) => expr.set_span(span),
179 Self::Ident(ident) => ident.set_span(span),
180 Self::Index(expr) => expr.set_span(span),
181 Self::Lit(lit) => lit.set_span(span),
182 Self::LitDenominated(lit) => lit.set_span(span),
183 Self::Member(expr) => expr.set_span(span),
184 Self::New(expr) => expr.set_span(span),
185 Self::Payable(expr) => expr.set_span(span),
186 Self::Postfix(expr) => expr.set_span(span),
187 Self::Ternary(expr) => expr.set_span(span),
188 Self::Tuple(expr) => expr.set_span(span),
189 Self::Type(ty) => ty.set_span(span),
190 Self::TypeCall(expr) => expr.set_span(span),
191 Self::Unary(expr) => expr.set_span(span),
192 }
193 }
194}
195
196impl Expr {
197 pub fn peel_parens(&self) -> &Self {
198 let mut expr = self;
199 while let Some(inner) = expr.peel_paren() {
200 expr = inner;
201 }
202 expr
203 }
204
205 fn peel_paren(&self) -> Option<&Self> {
206 if let Self::Tuple(t) = self {
207 if t.elems.len() == 1 {
208 return Some(&t.elems[0]);
209 }
210 }
211 None
212 }
213
214 fn parse_simple(input: ParseStream<'_>) -> Result<Self> {
215 let lookahead = input.lookahead1();
216 if lookahead.peek(Paren) {
217 input.parse().map(Self::Tuple)
218 } else if lookahead.peek(Bracket) {
219 input.parse().map(Self::Array)
220 } else if UnOp::peek(input, &lookahead) {
221 input.parse().map(Self::Unary)
222 } else if Lit::peek(&lookahead) {
223 match (input.parse()?, input.call(SubDenomination::parse_opt)?) {
224 (Lit::Number(number), Some(denom)) => {
225 Ok(Self::LitDenominated(LitDenominated { number, denom }))
226 }
227 (lit, None) => Ok(Self::Lit(lit)),
228 (_, Some(denom)) => {
229 Err(syn::Error::new(denom.span(), "unexpected subdenomination for literal"))
230 }
231 }
232 } else if lookahead.peek(kw::payable) {
233 input.parse().map(Self::Payable)
234 } else if lookahead.peek(Token![type]) {
235 input.parse().map(Self::TypeCall)
236 } else if lookahead.peek(kw::new) {
237 input.parse().map(Self::New)
238 } else if lookahead.peek(kw::delete) {
239 input.parse().map(Self::Delete)
240 } else if lookahead.peek(Ident::peek_any) {
241 let ident = input.call(Ident::parse_any)?;
242 let ty = Type::parse_ident(ident.clone()).parse_payable(input);
243 if ty.is_custom() {
244 Ok(Self::Ident(ident.into()))
245 } else {
246 Ok(Self::Type(ty))
247 }
248 } else {
249 Err(lookahead.error())
250 }
251 }
252
253 fn parse_nested(expr: Self, input: ParseStream<'_>) -> Result<(Self, bool)> {
257 macro_rules! parse {
258 (break) => {
259 Ok((expr, false))
260 };
261
262 ($map:expr) => {
263 ParseNested::parse_nested(expr.into(), input).map(|e| ($map(e), true))
264 };
265 }
266
267 let lookahead = input.lookahead1();
268 if lookahead.peek(Bracket) {
269 parse!(Self::Index)
270 } else if lookahead.peek(Brace) {
271 if input.peek2(kw::catch) {
273 parse!(break)
274 } else {
275 parse!(Self::CallOptions)
276 }
277 } else if lookahead.peek(Paren) {
278 parse!(Self::Call)
279 } else if lookahead.peek(Token![.]) {
280 parse!(Self::Member)
281 } else if lookahead.peek(Token![?]) {
282 parse!(Self::Ternary)
283 } else if PostUnOp::peek(input, &lookahead) {
284 parse!(Self::Postfix)
285 } else if BinOp::peek(input, &lookahead) {
286 parse!(Self::Binary)
287 } else {
288 parse!(break)
289 }
290 }
291}