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 fn parse_simple(input: ParseStream<'_>) -> Result<Self> {
198 let lookahead = input.lookahead1();
199 if lookahead.peek(Paren) {
200 input.parse().map(Self::Tuple)
201 } else if lookahead.peek(Bracket) {
202 input.parse().map(Self::Array)
203 } else if UnOp::peek(input, &lookahead) {
204 input.parse().map(Self::Unary)
205 } else if Lit::peek(&lookahead) {
206 match (input.parse()?, input.call(SubDenomination::parse_opt)?) {
207 (Lit::Number(number), Some(denom)) => {
208 Ok(Self::LitDenominated(LitDenominated { number, denom }))
209 }
210 (lit, None) => Ok(Self::Lit(lit)),
211 (_, Some(denom)) => {
212 Err(syn::Error::new(denom.span(), "unexpected subdenomination for literal"))
213 }
214 }
215 } else if lookahead.peek(kw::payable) {
216 input.parse().map(Self::Payable)
217 } else if lookahead.peek(Token![type]) {
218 input.parse().map(Self::TypeCall)
219 } else if lookahead.peek(kw::new) {
220 input.parse().map(Self::New)
221 } else if lookahead.peek(kw::delete) {
222 input.parse().map(Self::Delete)
223 } else if lookahead.peek(Ident::peek_any) {
224 let ident = input.call(Ident::parse_any)?;
225 match Type::parse_ident(ident.clone()) {
226 Ok(ty) if !ty.is_custom() => ty.parse_payable(input).map(Self::Type),
227 _ => Ok(Self::Ident(ident.into())),
228 }
229 } else {
230 Err(lookahead.error())
231 }
232 }
233
234 fn parse_nested(expr: Self, input: ParseStream<'_>) -> Result<(Self, bool)> {
238 macro_rules! parse {
239 (break) => {
240 Ok((expr, false))
241 };
242
243 ($map:expr) => {
244 ParseNested::parse_nested(expr.into(), input).map(|e| ($map(e), true))
245 };
246 }
247
248 let lookahead = input.lookahead1();
249 if lookahead.peek(Bracket) {
250 parse!(Self::Index)
251 } else if lookahead.peek(Brace) {
252 if input.peek2(kw::catch) {
254 parse!(break)
255 } else {
256 parse!(Self::CallOptions)
257 }
258 } else if lookahead.peek(Paren) {
259 parse!(Self::Call)
260 } else if lookahead.peek(Token![.]) {
261 parse!(Self::Member)
262 } else if lookahead.peek(Token![?]) {
263 parse!(Self::Ternary)
264 } else if PostUnOp::peek(input, &lookahead) {
265 parse!(Self::Postfix)
266 } else if BinOp::peek(input, &lookahead) {
267 parse!(Self::Binary)
268 } else {
269 parse!(break)
270 }
271 }
272}