1use super::{ExpectedToken, SeqSep};
2use crate::{PResult, Parser};
3use itertools::Itertools;
4use smallvec::SmallVec;
5use solar_ast::{token::*, *};
6use solar_interface::{diagnostics::DiagMsg, error_code, kw, sym, Ident, Span};
7
8impl<'sess, 'ast> Parser<'sess, 'ast> {
9 #[instrument(level = "debug", skip_all)]
11 pub fn parse_file(&mut self) -> PResult<'sess, SourceUnit<'ast>> {
12 self.parse_items(TokenKind::Eof).map(SourceUnit::new)
13 }
14
15 fn parse_items(&mut self, end: TokenKind) -> PResult<'sess, Box<'ast, [Item<'ast>]>> {
17 let get_msg_note = |this: &mut Self| {
18 let (prefix, list, link);
19 if this.in_contract {
20 prefix = "contract";
21 list = "function, variable, struct, or modifier definition";
22 link = "contractBodyElement";
23 } else {
24 prefix = "global";
25 list = "pragma, import directive, contract, interface, library, struct, enum, constant, function, modifier, or error definition";
26 link = "sourceUnit";
27 }
28 let msg =
29 format!("expected {prefix} item ({list}), found {}", this.token.full_description());
30 let note = format!("for a full list of valid {prefix} items, see <https://docs.soliditylang.org/en/latest/grammar.html#a4.SolidityParser.{link}>");
31 (msg, note)
32 };
33
34 let mut items = Vec::new();
35 while let Some(item) = self.parse_item()? {
36 if self.in_contract && !item.is_allowed_in_contract() {
37 let msg = format!("{}s are not allowed in contracts", item.description());
38 let (_, note) = get_msg_note(self);
39 self.dcx().err(msg).span(item.span).note(note).emit();
40 } else {
41 items.push(item);
42 }
43 }
44 if !self.eat(end) {
45 let (msg, note) = get_msg_note(self);
46 return Err(self.dcx().err(msg).span(self.token.span).note(note));
47 }
48 Ok(self.alloc_vec(items))
49 }
50
51 #[instrument(level = "debug", skip_all)]
53 pub fn parse_item(&mut self) -> PResult<'sess, Option<Item<'ast>>> {
54 let docs = self.parse_doc_comments();
55 self.parse_spanned(Self::parse_item_kind)
56 .map(|(span, kind)| kind.map(|kind| Item { docs, span, kind }))
57 }
58
59 fn parse_item_kind(&mut self) -> PResult<'sess, Option<ItemKind<'ast>>> {
60 let kind = if self.is_function_like() {
61 self.parse_function().map(ItemKind::Function)
62 } else if self.eat_keyword(kw::Struct) {
63 self.parse_struct().map(ItemKind::Struct)
64 } else if self.eat_keyword(kw::Event) {
65 self.parse_event().map(ItemKind::Event)
66 } else if self.is_contract_like() {
67 self.parse_contract().map(ItemKind::Contract)
68 } else if self.eat_keyword(kw::Enum) {
69 self.parse_enum().map(ItemKind::Enum)
70 } else if self.eat_keyword(kw::Type) {
71 self.parse_udvt().map(ItemKind::Udvt)
72 } else if self.eat_keyword(kw::Pragma) {
73 self.parse_pragma().map(ItemKind::Pragma)
74 } else if self.eat_keyword(kw::Import) {
75 self.parse_import().map(ItemKind::Import)
76 } else if self.eat_keyword(kw::Using) {
77 self.parse_using().map(ItemKind::Using)
78 } else if self.check_keyword(sym::error)
79 && self.look_ahead(1).is_ident()
80 && self.look_ahead(2).is_open_delim(Delimiter::Parenthesis)
81 {
82 self.bump(); self.parse_error().map(ItemKind::Error)
84 } else if self.is_variable_declaration() {
85 let flags = if self.in_contract { VarFlags::STATE_VAR } else { VarFlags::CONSTANT_VAR };
86 self.parse_variable_definition(flags).map(ItemKind::Variable)
87 } else {
88 return Ok(None);
89 };
90 kind.map(Some)
91 }
92
93 fn is_function_like(&self) -> bool {
95 (self.token.is_keyword(kw::Function)
96 && !self.look_ahead(1).is_open_delim(Delimiter::Parenthesis))
97 || self.token.is_keyword_any(&[
98 kw::Constructor,
99 kw::Fallback,
100 kw::Receive,
101 kw::Modifier,
102 ])
103 }
104
105 fn is_contract_like(&self) -> bool {
107 self.token.is_keyword_any(&[kw::Abstract, kw::Contract, kw::Interface, kw::Library])
108 }
109
110 pub(super) fn is_variable_declaration(&self) -> bool {
112 self.token.is_non_reserved_ident(false) || self.is_non_custom_variable_declaration()
114 }
115
116 pub(super) fn is_non_custom_variable_declaration(&self) -> bool {
117 self.token.is_keyword(kw::Mapping)
118 || (self.token.is_keyword(kw::Function)
119 && self.look_ahead(1).is_open_delim(Delimiter::Parenthesis))
120 || self.token.is_elementary_type()
121 }
122
123 fn parse_function(&mut self) -> PResult<'sess, ItemFunction<'ast>> {
130 let Token { span: lo, kind: TokenKind::Ident(kw) } = self.token else {
131 unreachable!("parse_function called without function-like keyword");
132 };
133 self.bump(); let kind = match kw {
136 kw::Constructor => FunctionKind::Constructor,
137 kw::Function => FunctionKind::Function,
138 kw::Fallback => FunctionKind::Fallback,
139 kw::Receive => FunctionKind::Receive,
140 kw::Modifier => FunctionKind::Modifier,
141 _ => unreachable!("parse_function called without function-like keyword"),
142 };
143 let flags = FunctionFlags::from_kind(kind);
144 let header = self.parse_function_header(flags)?;
145 let (body_span, body) = self.parse_spanned(|this| {
146 Ok(if !flags.contains(FunctionFlags::ONLY_BLOCK) && this.eat(TokenKind::Semi) {
147 None
148 } else {
149 Some(this.parse_block()?)
150 })
151 })?;
152
153 if !self.in_contract && !kind.allowed_in_global() {
154 let msg = format!("{kind}s are not allowed in the global scope");
155 self.dcx().err(msg).span(lo.to(self.prev_token.span)).emit();
156 }
157 Ok(ItemFunction { kind, header, body, body_span })
160 }
161
162 pub(super) fn parse_function_header(
164 &mut self,
165 flags: FunctionFlags,
166 ) -> PResult<'sess, FunctionHeader<'ast>> {
167 let mut header = FunctionHeader::default();
168 let var_flags = if flags.contains(FunctionFlags::PARAM_NAME) {
169 VarFlags::FUNCTION_TY
170 } else {
171 VarFlags::FUNCTION
172 };
173
174 if flags.contains(FunctionFlags::NAME) {
175 let ident;
177 if flags == FunctionFlags::FUNCTION
178 && self.token.is_keyword_any(&[kw::Fallback, kw::Receive])
179 {
180 let kw_span = self.prev_token.span;
181 ident = self.parse_ident_any()?;
182 let msg = format!("function named `{ident}`");
183 let mut warn = self.dcx().warn(msg).span(ident.span).code(error_code!(3445));
184 if self.in_contract {
185 let help = format!("remove the `function` keyword if you intend this to be a contract's {ident} function");
186 warn = warn.span_help(kw_span, help);
187 }
188 warn.emit();
189 } else {
190 ident = self.parse_ident()?;
191 }
192 header.name = Some(ident);
193 } else if self.token.is_non_reserved_ident(false) {
194 let msg = "function names are not allowed here";
195 self.dcx().err(msg).span(self.token.span).emit();
196 self.bump();
197 }
198
199 if flags.contains(FunctionFlags::NO_PARENS)
200 && !self.token.is_open_delim(Delimiter::Parenthesis)
201 {
202 } else {
204 header.parameters = self.parse_parameter_list(true, var_flags)?;
205 }
206
207 let mut modifiers = Vec::new();
208 loop {
209 let vis_guard = (!(flags == FunctionFlags::FUNCTION_TY && header.visibility.is_some()))
215 .then_some(());
216 if let Some(visibility) = vis_guard.and_then(|()| self.parse_visibility()) {
217 if !flags.contains(FunctionFlags::from_visibility(visibility)) {
218 let msg = visibility_error(visibility, flags.visibilities());
219 self.dcx().err(msg).span(self.prev_token.span).emit();
220 } else if header.visibility.is_some() {
221 let msg = "visibility already specified";
222 self.dcx().err(msg).span(self.prev_token.span).emit();
223 } else {
224 header.visibility = Some(visibility);
225 }
226 } else if let Some(state_mutability) = self.parse_state_mutability() {
227 if !flags.contains(FunctionFlags::from_state_mutability(state_mutability)) {
228 let msg = state_mutability_error(state_mutability, flags.state_mutabilities());
229 self.dcx().err(msg).span(self.prev_token.span).emit();
230 } else if !header.state_mutability.is_non_payable() {
231 let msg = "state mutability already specified";
232 self.dcx().err(msg).span(self.prev_token.span).emit();
233 } else {
234 header.state_mutability = state_mutability;
235 }
236 } else if self.eat_keyword(kw::Virtual) {
237 if !flags.contains(FunctionFlags::VIRTUAL) {
238 let msg = "`virtual` is not allowed here";
239 self.dcx().err(msg).span(self.prev_token.span).emit();
240 } else if header.virtual_ {
241 let msg = "virtual already specified";
242 self.dcx().err(msg).span(self.prev_token.span).emit();
243 } else {
244 header.virtual_ = true;
245 }
246 } else if self.eat_keyword(kw::Override) {
247 let o = self.parse_override()?;
248 if !flags.contains(FunctionFlags::OVERRIDE) {
249 let msg = "`override` is not allowed here";
250 self.dcx().err(msg).span(self.prev_token.span).emit();
251 } else if header.override_.is_some() {
252 let msg = "override already specified";
253 self.dcx().err(msg).span(self.prev_token.span).emit();
254 } else {
255 header.override_ = Some(o);
256 }
257 } else if flags.contains(FunctionFlags::MODIFIERS)
258 && self.token.is_non_reserved_ident(false)
259 {
260 modifiers.push(self.parse_modifier()?);
261 } else {
262 break;
263 }
264 }
265
266 header.modifiers = self.alloc_vec(modifiers);
267
268 if flags.contains(FunctionFlags::RETURNS) && self.eat_keyword(kw::Returns) {
269 header.returns = self.parse_parameter_list(false, var_flags)?;
270 }
271
272 Ok(header)
273 }
274
275 fn parse_struct(&mut self) -> PResult<'sess, ItemStruct<'ast>> {
277 let name = self.parse_ident()?;
278 let fields = self.parse_delim_seq(
279 Delimiter::Brace,
280 SeqSep::trailing_enforced(TokenKind::Semi),
281 true,
282 |this| this.parse_variable_definition(VarFlags::STRUCT),
283 )?;
284 Ok(ItemStruct { name, fields })
285 }
286
287 fn parse_event(&mut self) -> PResult<'sess, ItemEvent<'ast>> {
289 let name = self.parse_ident()?;
290 let parameters = self.parse_parameter_list(true, VarFlags::EVENT)?;
291 let anonymous = self.eat_keyword(kw::Anonymous);
292 self.expect_semi()?;
293 Ok(ItemEvent { name, parameters, anonymous })
294 }
295
296 fn parse_error(&mut self) -> PResult<'sess, ItemError<'ast>> {
298 let name = self.parse_ident()?;
299 let parameters = self.parse_parameter_list(true, VarFlags::ERROR)?;
300 self.expect_semi()?;
301 Ok(ItemError { name, parameters })
302 }
303
304 fn parse_contract(&mut self) -> PResult<'sess, ItemContract<'ast>> {
308 let TokenKind::Ident(kw) = self.token.kind else {
309 unreachable!("parse_contract called without contract-like keyword");
310 };
311 self.bump(); let kind = match kw {
314 kw::Abstract => {
315 self.expect_keyword(kw::Contract)?;
316 ContractKind::AbstractContract
317 }
318 kw::Contract => ContractKind::Contract,
319 kw::Interface => ContractKind::Interface,
320 kw::Library => ContractKind::Library,
321 _ => unreachable!("parse_contract called without contract-like keyword"),
322 };
323 let name = self.parse_ident()?;
324
325 let mut bases = None::<Box<'_, [Modifier<'_>]>>;
326 let mut layout = None::<StorageLayoutSpecifier<'_>>;
327 loop {
328 if self.eat_keyword(kw::Is) {
329 let new_bases = self.parse_inheritance()?;
330 if let Some(prev) = &bases {
331 let msg = "base contracts already specified";
332 let span = |bases: &[Modifier<'_>]| {
333 Span::join_first_last(bases.iter().map(|m| m.span()))
334 };
335 self.dcx()
336 .err(msg)
337 .span(span(new_bases))
338 .span_note(span(prev), "previous definition")
339 .emit();
340 } else if !new_bases.is_empty() {
341 bases = Some(new_bases);
342 }
343 } else if self.check_keyword(sym::layout) {
344 let new_layout = self.parse_storage_layout_specifier()?;
345 if let Some(prev) = &layout {
346 let msg = "storage layout already specified";
347 self.dcx()
348 .err(msg)
349 .span(new_layout.span)
350 .span_note(prev.span, "previous definition")
351 .emit();
352 } else {
353 layout = Some(new_layout);
354 }
355 } else {
356 break;
357 }
358 }
359
360 if let Some(layout) = &layout {
361 if !kind.is_contract() {
362 let msg = "storage layout is only allowed for contracts";
363 self.dcx().err(msg).span(layout.span).emit();
364 }
365 }
366
367 self.expect(TokenKind::OpenDelim(Delimiter::Brace))?;
368 let body =
369 self.in_contract(|this| this.parse_items(TokenKind::CloseDelim(Delimiter::Brace)))?;
370
371 Ok(ItemContract { kind, name, layout, bases: bases.unwrap_or_default(), body })
372 }
373
374 fn parse_enum(&mut self) -> PResult<'sess, ItemEnum<'ast>> {
376 let name = self.parse_ident()?;
377 let variants = self.parse_delim_comma_seq(Delimiter::Brace, true, Self::parse_ident)?;
378 Ok(ItemEnum { name, variants })
379 }
380
381 fn parse_udvt(&mut self) -> PResult<'sess, ItemUdvt<'ast>> {
383 let name = self.parse_ident()?;
384 self.expect_keyword(kw::Is)?;
385 let ty = self.parse_type()?;
386 self.expect_semi()?;
387 Ok(ItemUdvt { name, ty })
388 }
389
390 fn parse_pragma(&mut self) -> PResult<'sess, PragmaDirective<'ast>> {
392 let is_ident_or_strlit = |t: Token| t.is_ident() || t.is_str_lit();
393
394 let tokens = if self.check_keyword(sym::solidity)
395 || (self.token.is_ident()
396 && self.look_ahead_with(1, |t| t.is_op() || t.is_rational_lit()))
397 {
398 let ident = self.parse_ident_any()?;
400 let req = self.parse_semver_req()?;
401 PragmaTokens::Version(ident, req)
402 } else if (is_ident_or_strlit(self.token) && self.look_ahead(1).kind == TokenKind::Semi)
403 || (is_ident_or_strlit(self.token)
404 && self.look_ahead_with(1, is_ident_or_strlit)
405 && self.look_ahead(2).kind == TokenKind::Semi)
406 {
407 let k = self.parse_ident_or_strlit()?;
410 let v = if self.token.is_ident() || self.token.is_str_lit() {
411 Some(self.parse_ident_or_strlit()?)
412 } else {
413 None
414 };
415 PragmaTokens::Custom(k, v)
416 } else {
417 let mut tokens = Vec::new();
418 while !matches!(self.token.kind, TokenKind::Semi | TokenKind::Eof) {
419 tokens.push(self.token);
420 self.bump();
421 }
422 if !self.token.is_eof() && tokens.is_empty() {
423 let msg = "expected at least one token in pragma directive";
424 self.dcx().err(msg).span(self.prev_token.span).emit();
425 }
426 PragmaTokens::Verbatim(self.alloc_vec(tokens))
427 };
428 self.expect_semi()?;
429 Ok(PragmaDirective { tokens })
430 }
431
432 fn parse_ident_or_strlit(&mut self) -> PResult<'sess, IdentOrStrLit> {
433 if self.check_ident() {
434 self.parse_ident().map(IdentOrStrLit::Ident)
435 } else if self.check_str_lit() {
436 self.parse_str_lit().map(IdentOrStrLit::StrLit)
437 } else {
438 self.unexpected()
439 }
440 }
441
442 pub fn parse_semver_req(&mut self) -> PResult<'sess, SemverReq<'ast>> {
446 if self.check_noexpect(TokenKind::Semi) || self.check_noexpect(TokenKind::Eof) {
447 let msg = "empty version requirement";
448 let span = self.prev_token.span.to(self.token.span);
449 return Err(self.dcx().err(msg).span(span));
450 }
451 self.parse_semver_req_components_dis().map(|dis| SemverReq { dis })
452 }
453
454 fn parse_semver_req_components_dis(
456 &mut self,
457 ) -> PResult<'sess, Box<'ast, [SemverReqCon<'ast>]>> {
458 let mut dis = Vec::new();
460 loop {
461 dis.push(self.parse_semver_req_components_con()?);
462 if self.eat(TokenKind::OrOr) {
463 continue;
464 }
465 if self.check(TokenKind::Semi) || self.check(TokenKind::Eof) {
466 break;
467 }
468 debug_assert!(
471 matches!(
472 dis.last().map(|x| &x.components),
473 Some([
474 ..,
475 SemverReqComponent { span: _, kind: SemverReqComponentKind::Range(..) }
476 ])
477 ),
478 "not a range: last={:?}",
479 dis.last()
480 );
481 return Err(self.dcx().err("ranges can only be combined using the || operator"));
482 }
483 Ok(self.alloc_vec(dis))
484 }
485
486 fn parse_semver_req_components_con(&mut self) -> PResult<'sess, SemverReqCon<'ast>> {
488 let mut components = Vec::new();
492 let lo = self.token.span;
493 let (op, v) = self.parse_semver_component()?;
494 if self.eat(TokenKind::BinOp(BinOpToken::Minus)) {
495 let _ = op;
498 let (_second_op, right) = self.parse_semver_component()?;
499 let kind = SemverReqComponentKind::Range(v, right);
500 let span = lo.to(self.prev_token.span);
501 components.push(SemverReqComponent { span, kind });
502 } else {
503 let span = lo.to(self.prev_token.span);
505 let kind = SemverReqComponentKind::Op(op, v);
506 components.push(SemverReqComponent { span, kind });
507 while !matches!(self.token.kind, TokenKind::OrOr | TokenKind::Eof | TokenKind::Semi) {
509 let (span, (op, v)) = self.parse_spanned(Self::parse_semver_component)?;
510 let kind = SemverReqComponentKind::Op(op, v);
511 components.push(SemverReqComponent { span, kind });
512 }
513 }
514 let span = lo.to(self.prev_token.span);
515 let components = self.alloc_vec(components);
516 Ok(SemverReqCon { span, components })
517 }
518
519 fn parse_semver_component(&mut self) -> PResult<'sess, (Option<SemverOp>, SemverVersion)> {
520 let op = self.parse_semver_op();
521 let v = self.parse_semver_version()?;
522 Ok((op, v))
523 }
524
525 fn parse_semver_op(&mut self) -> Option<SemverOp> {
526 let op = match self.token.kind {
528 TokenKind::Eq => SemverOp::Exact,
529 TokenKind::Gt => SemverOp::Greater,
530 TokenKind::Ge => SemverOp::GreaterEq,
531 TokenKind::Lt => SemverOp::Less,
532 TokenKind::Le => SemverOp::LessEq,
533 TokenKind::Tilde => SemverOp::Tilde,
534 TokenKind::BinOp(BinOpToken::Caret) => SemverOp::Caret,
535 _ => return None,
536 };
537 self.bump();
538 Some(op)
539 }
540
541 fn parse_semver_version(&mut self) -> PResult<'sess, SemverVersion> {
542 Ok(SemverVersionParser::new(self).parse())
543 }
544
545 fn parse_import(&mut self) -> PResult<'sess, ImportDirective<'ast>> {
547 let path;
548 let items = if self.eat(TokenKind::BinOp(BinOpToken::Star)) {
549 let alias = self.parse_as_alias()?;
551 self.expect_keyword(sym::from)?;
552 path = self.parse_str_lit()?;
553 ImportItems::Glob(alias)
554 } else if self.check(TokenKind::OpenDelim(Delimiter::Brace)) {
555 let list = self.parse_delim_comma_seq(Delimiter::Brace, false, |this| {
557 let name = this.parse_ident()?;
558 let alias = this.parse_as_alias_opt()?;
559 Ok((name, alias))
560 })?;
561 self.expect_keyword(sym::from)?;
562 path = self.parse_str_lit()?;
563 ImportItems::Aliases(list)
564 } else {
565 path = self.parse_str_lit()?;
567 let alias = self.parse_as_alias_opt()?;
568 ImportItems::Plain(alias)
569 };
570 if path.value.as_str().is_empty() {
571 let msg = "import path cannot be empty";
572 self.dcx().err(msg).span(path.span).emit();
573 }
574 self.expect_semi()?;
575 Ok(ImportDirective { path, items })
576 }
577
578 fn parse_as_alias_opt(&mut self) -> PResult<'sess, Option<Ident>> {
580 if self.eat_keyword(kw::As) {
581 self.parse_ident().map(Some)
582 } else {
583 Ok(None)
584 }
585 }
586
587 fn parse_as_alias(&mut self) -> PResult<'sess, Ident> {
589 self.expect_keyword(kw::As)?;
590 self.parse_ident()
591 }
592
593 fn parse_using(&mut self) -> PResult<'sess, UsingDirective<'ast>> {
595 let list = self.parse_using_list()?;
596 self.expect_keyword(kw::For)?;
597 let ty = if self.eat(TokenKind::BinOp(BinOpToken::Star)) {
598 None
599 } else {
600 Some(self.parse_type()?)
601 };
602 let global = self.eat_keyword(sym::global);
603 self.expect_semi()?;
604 Ok(UsingDirective { list, ty, global })
605 }
606
607 fn parse_using_list(&mut self) -> PResult<'sess, UsingList<'ast>> {
608 if self.check(TokenKind::OpenDelim(Delimiter::Brace)) {
609 self.parse_delim_comma_seq(Delimiter::Brace, false, |this| {
610 let path = this.parse_path()?;
611 let op = if this.eat_keyword(kw::As) {
612 Some(this.parse_user_definable_operator()?)
613 } else {
614 None
615 };
616 Ok((path, op))
617 })
618 .map(UsingList::Multiple)
619 } else {
620 self.parse_path().map(UsingList::Single)
621 }
622 }
623
624 fn parse_user_definable_operator(&mut self) -> PResult<'sess, UserDefinableOperator> {
625 use BinOpToken::*;
626 use TokenKind::*;
627 use UserDefinableOperator as Op;
628 macro_rules! user_op {
629 ($($tok1:tt $(($tok2:tt))? => $op:expr),* $(,)?) => {
630 match self.token.kind {
631 $($tok1 $(($tok2))? => $op,)*
632 _ => {
633 self.expected_tokens.extend_from_slice(&[$(ExpectedToken::Token($tok1 $(($tok2))?)),*]);
634 return self.unexpected();
635 }
636 }
637 };
638 }
639 let op = user_op! {
640 BinOp(And) => Op::BitAnd,
641 Tilde => Op::BitNot,
642 BinOp(Or) => Op::BitOr,
643 BinOp(Caret) => Op::BitXor,
644 BinOp(Plus) => Op::Add,
645 BinOp(Slash) => Op::Div,
646 BinOp(Percent) => Op::Rem,
647 BinOp(Star) => Op::Mul,
648 BinOp(Minus) => Op::Sub,
649 EqEq => Op::Eq,
650 Ge => Op::Ge,
651 Gt => Op::Gt,
652 Le => Op::Le,
653 Lt => Op::Lt,
654 Ne => Op::Ne,
655 };
656 self.bump();
657 Ok(op)
658 }
659
660 pub(super) fn parse_variable_definition(
667 &mut self,
668 flags: VarFlags,
669 ) -> PResult<'sess, VariableDefinition<'ast>> {
670 self.parse_variable_definition_with(flags, None)
671 }
672
673 pub(super) fn parse_variable_definition_with(
674 &mut self,
675 flags: VarFlags,
676 ty: Option<Type<'ast>>,
677 ) -> PResult<'sess, VariableDefinition<'ast>> {
678 let mut lo = self.token.span;
679 let ty = match ty {
680 Some(ty) => {
681 lo = lo.with_lo(ty.span.lo());
682 ty
683 }
684 None => self.parse_type()?,
685 };
686
687 if ty.is_function()
688 && flags == VarFlags::STATE_VAR
689 && self.check_noexpect(TokenKind::OpenDelim(Delimiter::Brace))
690 {
691 let msg = "expected a state variable declaration";
692 let note = "this style of fallback function has been removed; use the `fallback` or `receive` keywords instead";
693 self.dcx().err(msg).span(self.token.span).note(note).emit();
694 let _ = self.parse_block()?;
695 return Ok(VariableDefinition {
696 span: lo.to(self.prev_token.span),
697 ty,
698 visibility: None,
699 mutability: None,
700 data_location: None,
701 override_: None,
702 indexed: false,
703 name: None,
704 initializer: None,
705 });
706 }
707
708 let mut data_location = None;
709 let mut visibility = None;
710 let mut mutability = None;
711 let mut override_ = None;
712 let mut indexed = false;
713 loop {
714 if let Some(s) = self.parse_data_location() {
715 if !flags.contains(VarFlags::DATALOC) {
716 let msg = "data locations are not allowed here";
717 self.dcx().err(msg).span(self.prev_token.span).emit();
718 } else if data_location.is_some() {
719 let msg = "data location already specified";
720 self.dcx().err(msg).span(self.prev_token.span).emit();
721 } else {
722 data_location = Some(s);
723 }
724 } else if let Some(v) = self.parse_visibility() {
725 if !flags.contains(VarFlags::from_visibility(v)) {
726 let msg = visibility_error(v, flags.visibilities());
727 self.dcx().err(msg).span(self.prev_token.span).emit();
728 } else if visibility.is_some() {
729 let msg = "visibility already specified";
730 self.dcx().err(msg).span(self.prev_token.span).emit();
731 } else {
732 visibility = Some(v);
733 }
734 } else if let Some(m) = self.parse_variable_mutability() {
735 if flags != VarFlags::CONSTANT_VAR && !flags.contains(VarFlags::from_varmut(m)) {
737 let msg = varmut_error(m, flags.varmuts());
738 self.dcx().err(msg).span(self.prev_token.span).emit();
739 } else if mutability.is_some() {
740 let msg = "mutability already specified";
741 self.dcx().err(msg).span(self.prev_token.span).emit();
742 } else {
743 mutability = Some(m);
744 }
745 } else if self.eat_keyword(kw::Indexed) {
746 if !flags.contains(VarFlags::INDEXED) {
747 let msg = "`indexed` is not allowed here";
748 self.dcx().err(msg).span(self.prev_token.span).emit();
749 } else if indexed {
750 let msg = "`indexed` already specified";
751 self.dcx().err(msg).span(self.prev_token.span).emit();
752 } else {
753 indexed = true;
754 }
755 } else if self.eat_keyword(kw::Virtual) {
756 let msg = "`virtual` is not allowed here";
757 self.dcx().err(msg).span(self.prev_token.span).emit();
758 } else if self.eat_keyword(kw::Override) {
759 let o = self.parse_override()?;
760 if !flags.contains(VarFlags::OVERRIDE) {
761 let msg = "`override` is not allowed here";
762 self.dcx().err(msg).span(self.prev_token.span).emit();
763 } else if override_.is_some() {
764 let msg = "override already specified";
765 self.dcx().err(msg).span(self.prev_token.span).emit();
766 } else {
767 override_ = Some(o);
768 }
769 } else {
770 break;
771 }
772 }
773
774 let name = if flags.contains(VarFlags::NAME) {
775 self.parse_ident().map(Some)
776 } else {
777 self.parse_ident_opt()
778 }?;
779 if let Some(name) = &name {
780 if flags.contains(VarFlags::NAME_WARN) {
781 debug_assert!(!flags.contains(VarFlags::NAME));
782 let msg = "named function type parameters are deprecated";
783 self.dcx().warn(msg).code(error_code!(6162)).span(name.span).emit();
784 }
785 }
786
787 let initializer = if flags.contains(VarFlags::INITIALIZER) && self.eat(TokenKind::Eq) {
788 Some(self.parse_expr()?)
789 } else {
790 None
791 };
792
793 if flags.contains(VarFlags::SEMI) {
794 self.expect_semi()?;
795 }
796
797 let span = lo.to(self.prev_token.span);
798
799 if mutability == Some(VarMut::Constant) && initializer.is_none() {
800 let msg = "constant variable must be initialized";
801 self.dcx().err(msg).span(span).emit();
802 }
803 if flags == VarFlags::CONSTANT_VAR && mutability != Some(VarMut::Constant) {
804 let msg = "only constant variables are allowed at file level";
805 self.dcx().err(msg).span(span).emit();
806 }
807
808 Ok(VariableDefinition {
809 span,
810 ty,
811 data_location,
812 visibility,
813 mutability,
814 override_,
815 indexed,
816 name,
817 initializer,
818 })
819 }
820
821 fn parse_variable_mutability(&mut self) -> Option<VarMut> {
823 if self.eat_keyword(kw::Constant) {
824 Some(VarMut::Constant)
825 } else if self.eat_keyword(kw::Immutable) {
826 Some(VarMut::Immutable)
827 } else {
828 None
829 }
830 }
831
832 pub(super) fn parse_parameter_list(
834 &mut self,
835 allow_empty: bool,
836 flags: VarFlags,
837 ) -> PResult<'sess, ParameterList<'ast>> {
838 self.parse_paren_comma_seq(allow_empty, |this| this.parse_variable_definition(flags))
839 }
840
841 fn parse_inheritance(&mut self) -> PResult<'sess, Box<'ast, [Modifier<'ast>]>> {
843 let mut list = SmallVec::<[_; 8]>::new();
844 loop {
845 list.push(self.parse_modifier()?);
846 if !self.eat(TokenKind::Comma) {
847 break;
848 }
849 }
850 Ok(self.alloc_smallvec(list))
851 }
852
853 fn parse_storage_layout_specifier(&mut self) -> PResult<'sess, StorageLayoutSpecifier<'ast>> {
855 let lo = self.token.span;
856 self.expect_keyword(sym::layout)?;
857 self.expect_keyword(sym::at)?;
858 let slot = self.parse_expr()?;
859 Ok(StorageLayoutSpecifier { span: lo.to(self.prev_token.span), slot })
860 }
861
862 fn parse_modifier(&mut self) -> PResult<'sess, Modifier<'ast>> {
864 let name = self.parse_path()?;
865 let arguments = if self.token.kind == TokenKind::OpenDelim(Delimiter::Parenthesis) {
866 self.parse_call_args()?
867 } else {
868 CallArgs::empty()
869 };
870 Ok(Modifier { name, arguments })
871 }
872
873 fn parse_override(&mut self) -> PResult<'sess, Override<'ast>> {
877 debug_assert!(self.prev_token.is_keyword(kw::Override));
878 let lo = self.prev_token.span;
879 let paths = if self.token.is_open_delim(Delimiter::Parenthesis) {
880 self.parse_paren_comma_seq(false, Self::parse_path)?
881 } else {
882 Default::default()
883 };
884 let span = lo.to(self.prev_token.span);
885 Ok(Override { span, paths })
886 }
887
888 pub(super) fn parse_str_lit(&mut self) -> PResult<'sess, StrLit> {
891 match self.parse_str_lit_opt() {
892 Some(lit) => Ok(lit),
893 None => self.unexpected(),
894 }
895 }
896
897 pub(super) fn parse_str_lit_opt(&mut self) -> Option<StrLit> {
900 if !self.check_str_lit() {
901 return None;
902 }
903 let Token { kind: TokenKind::Literal(TokenLitKind::Str, symbol), span } = self.token else {
904 unreachable!()
905 };
906 self.bump();
907 Some(StrLit { span, value: symbol })
908 }
909
910 fn parse_data_location(&mut self) -> Option<DataLocation> {
912 if self.eat_keyword(kw::Storage) {
913 Some(DataLocation::Storage)
914 } else if self.eat_keyword(kw::Memory) {
915 Some(DataLocation::Memory)
916 } else if self.eat_keyword(kw::Calldata) {
917 Some(DataLocation::Calldata)
918 } else if self.check_keyword(sym::transient)
919 && !matches!(
920 self.look_ahead(1).kind,
921 TokenKind::Eq | TokenKind::Semi | TokenKind::CloseDelim(_) | TokenKind::Comma
922 )
923 {
924 self.bump(); Some(DataLocation::Transient)
926 } else {
927 None
928 }
929 }
930
931 pub(super) fn parse_visibility(&mut self) -> Option<Visibility> {
933 if self.eat_keyword(kw::Public) {
934 Some(Visibility::Public)
935 } else if self.eat_keyword(kw::Private) {
936 Some(Visibility::Private)
937 } else if self.eat_keyword(kw::Internal) {
938 Some(Visibility::Internal)
939 } else if self.eat_keyword(kw::External) {
940 Some(Visibility::External)
941 } else {
942 None
943 }
944 }
945
946 pub(super) fn parse_state_mutability(&mut self) -> Option<StateMutability> {
948 if self.eat_keyword(kw::Payable) {
949 Some(StateMutability::Payable)
950 } else if self.eat_keyword(kw::Pure) {
951 Some(StateMutability::Pure)
952 } else if self.eat_keyword(kw::View) {
953 Some(StateMutability::View)
954 } else {
955 None
956 }
957 }
958}
959
960struct SemverVersionParser<'p, 'sess, 'ast> {
961 p: &'p mut Parser<'sess, 'ast>,
962 bumps: u32,
963 pos_inside: u32,
964}
965
966impl<'p, 'sess, 'ast> SemverVersionParser<'p, 'sess, 'ast> {
967 fn new(p: &'p mut Parser<'sess, 'ast>) -> Self {
968 Self { p, bumps: 0, pos_inside: 0 }
969 }
970
971 fn emit_err(&self, msg: impl Into<DiagMsg>) {
972 self.p.dcx().err(msg).span(self.current_span()).emit();
973 }
974
975 fn parse(mut self) -> SemverVersion {
976 let lo = self.current_span();
977 let major = self.parse_version_part();
978 let mut minor = None;
979 let mut patch = None;
980 if self.eat_dot() {
981 minor = Some(self.parse_version_part());
982 if self.eat_dot() {
983 patch = Some(self.parse_version_part());
984 }
985 }
986 if self.pos_inside > 0 || self.bumps == 0 {
987 self.emit_err("unexpected trailing characters");
988 self.bump_token();
989 }
990 SemverVersion { span: lo.to(self.current_span()), major, minor, patch }
991 }
992
993 fn eat_dot(&mut self) -> bool {
994 let r = self.current_char() == Some('.');
995 if r {
996 self.bump_char();
997 }
998 r
999 }
1000
1001 fn parse_version_part(&mut self) -> SemverVersionNumber {
1002 match self.current_char() {
1003 Some('*' | 'x' | 'X') => {
1004 self.bump_char();
1005 SemverVersionNumber::Wildcard
1006 }
1007 Some('0'..='9') => {
1008 let s = self.current_str().unwrap();
1009 let len = s.bytes().take_while(u8::is_ascii_digit).count();
1010 let result = s[..len].parse();
1011 self.bump_chars(len as u32);
1012 let Ok(n) = result else {
1013 self.emit_err("version number too large");
1014 return SemverVersionNumber::Wildcard;
1015 };
1016 SemverVersionNumber::Number(n)
1017 }
1018 _ => {
1019 self.emit_err("expected version number");
1020 self.bump_char();
1021 SemverVersionNumber::Wildcard
1022 }
1023 }
1024 }
1025
1026 fn current_char(&self) -> Option<char> {
1027 self.current_str()?.chars().next()
1028 }
1029
1030 fn current_str(&self) -> Option<&str> {
1031 self.current_token_str()?.get(self.pos_inside as usize..)
1032 }
1033
1034 fn current_token_str(&self) -> Option<&str> {
1035 Some(match &self.current_token().kind {
1036 TokenKind::Dot => ".",
1037 TokenKind::BinOp(BinOpToken::Star) => "*",
1038 TokenKind::Ident(s) | TokenKind::Literal(_, s) => s.as_str(),
1039 _ => return None,
1040 })
1041 }
1042
1043 fn current_token(&self) -> &Token {
1044 &self.p.token
1045 }
1046
1047 fn current_span(&self) -> Span {
1048 let mut s = self.current_token().span;
1049 if self.pos_inside > 0 {
1050 s = s.with_lo(s.lo() + self.pos_inside);
1051 }
1052 s
1053 }
1054
1055 fn bump_char(&mut self) {
1056 self.bump_chars(1);
1057 }
1058
1059 fn bump_chars(&mut self, n: u32) {
1060 if let Some(s) = self.current_token_str() {
1061 if self.pos_inside + n >= s.len() as u32 {
1062 self.bump_token();
1063 } else {
1064 self.pos_inside += n;
1065 }
1066 }
1067 }
1068
1069 fn bump_token(&mut self) {
1070 self.p.bump();
1071 self.bumps += 1;
1072 self.pos_inside = 0;
1073 }
1074}
1075
1076bitflags::bitflags! {
1077 #[derive(Clone, Copy, PartialEq, Eq)]
1079 pub(super) struct VarFlags: u16 {
1080 const DATALOC = 1 << 1;
1083 const INDEXED = 1 << 2;
1084
1085 const PRIVATE = 1 << 3;
1086 const INTERNAL = 1 << 4;
1087 const PUBLIC = 1 << 5;
1088 const EXTERNAL = 1 << 6; const VISIBILITY = Self::PRIVATE.bits()
1090 | Self::INTERNAL.bits()
1091 | Self::PUBLIC.bits()
1092 | Self::EXTERNAL.bits();
1093
1094 const CONSTANT = 1 << 7;
1095 const IMMUTABLE = 1 << 8;
1096
1097 const OVERRIDE = 1 << 9;
1098
1099 const NAME = 1 << 10;
1100 const NAME_WARN = 1 << 11;
1101
1102 const INITIALIZER = 1 << 12;
1103 const SEMI = 1 << 13;
1104
1105 const STRUCT = Self::NAME.bits();
1106 const ERROR = 0;
1107 const EVENT = Self::INDEXED.bits();
1108 const FUNCTION = Self::DATALOC.bits();
1109 const FUNCTION_TY = Self::DATALOC.bits() | Self::NAME_WARN.bits();
1110
1111 const STATE_VAR = Self::DATALOC.bits()
1113 | Self::PRIVATE.bits()
1114 | Self::INTERNAL.bits()
1115 | Self::PUBLIC.bits()
1116 | Self::CONSTANT.bits()
1117 | Self::IMMUTABLE.bits()
1118 | Self::OVERRIDE.bits()
1119 | Self::NAME.bits()
1120 | Self::INITIALIZER.bits()
1121 | Self::SEMI.bits();
1122
1123 const CONSTANT_VAR = Self::CONSTANT.bits()
1125 | Self::NAME.bits()
1126 | Self::INITIALIZER.bits()
1127 | Self::SEMI.bits();
1128
1129 const VAR = Self::DATALOC.bits() | Self::INITIALIZER.bits();
1131 }
1132
1133 #[derive(Clone, Copy, PartialEq, Eq)]
1135 pub(super) struct FunctionFlags: u16 {
1136 const NAME = 1 << 0;
1138 const PARAM_NAME = 1 << 1;
1140 const NO_PARENS = 1 << 2;
1142
1143 const PRIVATE = 1 << 3;
1145 const INTERNAL = 1 << 4;
1146 const PUBLIC = 1 << 5;
1147 const EXTERNAL = 1 << 6;
1148 const VISIBILITY = Self::PRIVATE.bits()
1149 | Self::INTERNAL.bits()
1150 | Self::PUBLIC.bits()
1151 | Self::EXTERNAL.bits();
1152
1153 const PURE = 1 << 7;
1155 const VIEW = 1 << 8;
1156 const PAYABLE = 1 << 9;
1157 const STATE_MUTABILITY = Self::PURE.bits()
1158 | Self::VIEW.bits()
1159 | Self::PAYABLE.bits();
1160
1161 const MODIFIERS = 1 << 10;
1162 const VIRTUAL = 1 << 11;
1163 const OVERRIDE = 1 << 12;
1164
1165 const RETURNS = 1 << 13;
1166 const ONLY_BLOCK = 1 << 14;
1168
1169 const CONSTRUCTOR = Self::MODIFIERS.bits()
1171 | Self::PAYABLE.bits()
1172 | Self::INTERNAL.bits()
1173 | Self::PUBLIC.bits()
1174 | Self::ONLY_BLOCK.bits();
1175
1176 const FUNCTION = Self::NAME.bits()
1178 | Self::VISIBILITY.bits()
1179 | Self::STATE_MUTABILITY.bits()
1180 | Self::MODIFIERS.bits()
1181 | Self::VIRTUAL.bits()
1182 | Self::OVERRIDE.bits()
1183 | Self::RETURNS.bits();
1184
1185 const MODIFIER = Self::NAME.bits()
1187 | Self::NO_PARENS.bits()
1188 | Self::VIRTUAL.bits()
1189 | Self::OVERRIDE.bits();
1190
1191 const FALLBACK = Self::EXTERNAL.bits()
1193 | Self::STATE_MUTABILITY.bits()
1194 | Self::MODIFIERS.bits()
1195 | Self::VIRTUAL.bits()
1196 | Self::OVERRIDE.bits()
1197 | Self::RETURNS.bits();
1198
1199 const RECEIVE = Self::EXTERNAL.bits()
1201 | Self::PAYABLE.bits()
1202 | Self::MODIFIERS.bits()
1203 | Self::VIRTUAL.bits()
1204 | Self::OVERRIDE.bits();
1205
1206 const FUNCTION_TY = Self::PARAM_NAME.bits()
1208 | Self::VISIBILITY.bits()
1209 | Self::STATE_MUTABILITY.bits()
1210 | Self::RETURNS.bits();
1211 }
1212}
1213
1214impl VarFlags {
1215 fn from_visibility(v: Visibility) -> Self {
1216 match v {
1217 Visibility::Private => Self::PRIVATE,
1218 Visibility::Internal => Self::INTERNAL,
1219 Visibility::Public => Self::PUBLIC,
1220 Visibility::External => Self::EXTERNAL,
1221 }
1222 }
1223
1224 fn into_visibility(self) -> Option<Visibility> {
1225 match self {
1226 Self::PRIVATE => Some(Visibility::Private),
1227 Self::INTERNAL => Some(Visibility::Internal),
1228 Self::PUBLIC => Some(Visibility::Public),
1229 Self::EXTERNAL => Some(Visibility::External),
1230 _ => None,
1231 }
1232 }
1233
1234 fn visibilities(self) -> Option<impl Iterator<Item = Visibility>> {
1235 self.supported(Self::VISIBILITY).map(|iter| iter.map(|x| x.into_visibility().unwrap()))
1236 }
1237
1238 fn from_varmut(v: VarMut) -> Self {
1239 match v {
1240 VarMut::Constant => Self::CONSTANT,
1241 VarMut::Immutable => Self::IMMUTABLE,
1242 }
1243 }
1244
1245 fn into_varmut(self) -> Option<VarMut> {
1246 match self {
1247 Self::CONSTANT => Some(VarMut::Constant),
1248 Self::IMMUTABLE => Some(VarMut::Immutable),
1249 _ => None,
1250 }
1251 }
1252
1253 fn varmuts(self) -> Option<impl Iterator<Item = VarMut>> {
1254 self.supported(Self::CONSTANT | Self::IMMUTABLE)
1255 .map(|iter| iter.map(|x| x.into_varmut().unwrap()))
1256 }
1257
1258 fn supported(self, what: Self) -> Option<impl Iterator<Item = Self>> {
1259 let s = self.intersection(what);
1260 if s.is_empty() {
1261 None
1262 } else {
1263 Some(s.iter())
1264 }
1265 }
1266}
1267
1268impl FunctionFlags {
1269 fn from_kind(kind: FunctionKind) -> Self {
1270 match kind {
1271 FunctionKind::Constructor => Self::CONSTRUCTOR,
1272 FunctionKind::Function => Self::FUNCTION,
1273 FunctionKind::Modifier => Self::MODIFIER,
1274 FunctionKind::Receive => Self::RECEIVE,
1275 FunctionKind::Fallback => Self::FALLBACK,
1276 }
1277 }
1278
1279 fn from_visibility(visibility: Visibility) -> Self {
1280 match visibility {
1281 Visibility::Private => Self::PRIVATE,
1282 Visibility::Internal => Self::INTERNAL,
1283 Visibility::Public => Self::PUBLIC,
1284 Visibility::External => Self::EXTERNAL,
1285 }
1286 }
1287
1288 fn into_visibility(self) -> Option<Visibility> {
1289 match self {
1290 Self::PRIVATE => Some(Visibility::Private),
1291 Self::INTERNAL => Some(Visibility::Internal),
1292 Self::PUBLIC => Some(Visibility::Public),
1293 Self::EXTERNAL => Some(Visibility::External),
1294 _ => None,
1295 }
1296 }
1297
1298 fn visibilities(self) -> Option<impl Iterator<Item = Visibility>> {
1299 self.supported(Self::VISIBILITY).map(|iter| iter.map(|x| x.into_visibility().unwrap()))
1300 }
1301
1302 fn from_state_mutability(state_mutability: StateMutability) -> Self {
1303 match state_mutability {
1304 StateMutability::Pure => Self::PURE,
1305 StateMutability::View => Self::VIEW,
1306 StateMutability::Payable => Self::PAYABLE,
1307 StateMutability::NonPayable => unreachable!(),
1308 }
1309 }
1310
1311 fn into_state_mutability(self) -> Option<StateMutability> {
1312 match self {
1313 Self::PURE => Some(StateMutability::Pure),
1314 Self::VIEW => Some(StateMutability::View),
1315 Self::PAYABLE => Some(StateMutability::Payable),
1316 _ => None,
1317 }
1318 }
1319
1320 fn state_mutabilities(self) -> Option<impl Iterator<Item = StateMutability>> {
1321 self.supported(Self::STATE_MUTABILITY)
1322 .map(|iter| iter.map(|x| x.into_state_mutability().unwrap()))
1323 }
1324
1325 fn supported(self, what: Self) -> Option<impl Iterator<Item = Self>> {
1326 let s = self.intersection(what);
1327 if s.is_empty() {
1328 None
1329 } else {
1330 Some(s.iter())
1331 }
1332 }
1333}
1334
1335fn visibility_error(v: Visibility, iter: Option<impl Iterator<Item = Visibility>>) -> String {
1336 common_flags_error(v, "visibility", iter)
1337}
1338
1339fn varmut_error(m: VarMut, iter: Option<impl Iterator<Item = VarMut>>) -> String {
1340 common_flags_error(m, "mutability", iter)
1341}
1342
1343fn state_mutability_error(
1344 m: StateMutability,
1345 iter: Option<impl Iterator<Item = StateMutability>>,
1346) -> String {
1347 common_flags_error(m, "state mutability", iter)
1348}
1349
1350fn common_flags_error<T: std::fmt::Display>(
1351 t: T,
1352 desc: &str,
1353 iter: Option<impl Iterator<Item = T>>,
1354) -> String {
1355 match iter {
1356 Some(iter) => format!("`{t}` not allowed here; allowed values: {}", iter.format(", ")),
1357 None => format!("{desc} is not allowed here"),
1358 }
1359}
1360
1361#[cfg(test)]
1362mod tests {
1363 use super::*;
1364 use solar_interface::{source_map::FileName, Result, Session};
1365
1366 fn assert_version_matches(tests: &[(&str, &str, bool)]) {
1367 let sess = Session::builder().with_test_emitter().build();
1368 sess.enter(|| -> Result {
1369 for (i, &(v, req_s, res)) in tests.iter().enumerate() {
1370 let name = i.to_string();
1371 let src = format!("{v} {req_s}");
1372 let arena = Arena::new();
1373 let mut parser =
1374 Parser::from_source_code(&sess, &arena, FileName::Custom(name), src)?;
1375
1376 let version = parser.parse_semver_version().map_err(|e| e.emit()).unwrap();
1377 assert_eq!(version.to_string(), v);
1378 let req: SemverReq<'_> = parser.parse_semver_req().map_err(|e| e.emit()).unwrap();
1379 sess.dcx.has_errors().unwrap();
1380 assert_eq!(req.matches(&version), res, "v={v:?}, req={req_s:?}");
1381 }
1382 Ok(())
1383 })
1384 .unwrap();
1385 }
1386
1387 #[test]
1388 fn semver_matches() {
1389 assert_version_matches(&[
1390 ("0.8.1", "0", true),
1392 ("0.8.1", "1", false),
1393 ("0.8.1", "1.0", false),
1394 ("0.8.1", "1.0.0", false),
1395 ("0.8.1", "0.7", false),
1396 ("0.8.1", "0.7.0", false),
1397 ("0.8.1", "0.7.1", false),
1398 ("0.8.1", "0.7.2", false),
1399 ("0.8.1", "0.8", true),
1400 ("0.8.1", "0.8.0", false),
1401 ("0.8.1", "0.8.1", true),
1402 ("0.8.1", "0.8.2", false),
1403 ("0.8.1", "0.9", false),
1404 ("0.8.1", "0.9.0", false),
1405 ("0.8.1", "0.9.1", false),
1406 ("0.8.1", "0.9.2", false),
1407 ("0.8.1", "=0", true),
1409 ("0.8.1", "=1", false),
1410 ("0.8.1", "=1.0", false),
1411 ("0.8.1", "=1.0.0", false),
1412 ("0.8.1", "=0.7", false),
1413 ("0.8.1", "=0.7.0", false),
1414 ("0.8.1", "=0.7.1", false),
1415 ("0.8.1", "=0.7.2", false),
1416 ("0.8.1", "=0.8", true),
1417 ("0.8.1", "=0.8.0", false),
1418 ("0.8.1", "=0.8.1", true),
1419 ("0.8.1", "=0.8.2", false),
1420 ("0.8.1", "=0.9", false),
1421 ("0.8.1", "=0.9.0", false),
1422 ("0.8.1", "=0.9.1", false),
1423 ("0.8.1", "=0.9.2", false),
1424 ("0.8.1", ">0", false),
1426 ("0.8.1", ">1", false),
1427 ("0.8.1", ">1.0", false),
1428 ("0.8.1", ">1.0.0", false),
1429 ("0.8.1", ">0.7", true),
1430 ("0.8.1", ">0.7.0", true),
1431 ("0.8.1", ">0.7.1", true),
1432 ("0.8.1", ">0.7.2", true),
1433 ("0.8.1", ">0.8", false),
1434 ("0.8.1", ">0.8.0", true),
1435 ("0.8.1", ">0.8.1", false),
1436 ("0.8.1", ">0.8.2", false),
1437 ("0.8.1", ">0.9", false),
1438 ("0.8.1", ">0.9.0", false),
1439 ("0.8.1", ">0.9.1", false),
1440 ("0.8.1", ">0.9.2", false),
1441 ("0.8.1", ">=0", true),
1443 ("0.8.1", ">=1", false),
1444 ("0.8.1", ">=1.0", false),
1445 ("0.8.1", ">=1.0.0", false),
1446 ("0.8.1", ">=0.7", true),
1447 ("0.8.1", ">=0.7.0", true),
1448 ("0.8.1", ">=0.7.1", true),
1449 ("0.8.1", ">=0.7.2", true),
1450 ("0.8.1", ">=0.8", true),
1451 ("0.8.1", ">=0.8.0", true),
1452 ("0.8.1", ">=0.8.1", true),
1453 ("0.8.1", ">=0.8.2", false),
1454 ("0.8.1", ">=0.9", false),
1455 ("0.8.1", ">=0.9.0", false),
1456 ("0.8.1", ">=0.9.1", false),
1457 ("0.8.1", ">=0.9.2", false),
1458 ("0.8.1", "<0", false),
1460 ("0.8.1", "<1", true),
1461 ("0.8.1", "<1.0", true),
1462 ("0.8.1", "<1.0.0", true),
1463 ("0.8.1", "<0.7", false),
1464 ("0.8.1", "<0.7.0", false),
1465 ("0.8.1", "<0.7.1", false),
1466 ("0.8.1", "<0.7.2", false),
1467 ("0.8.1", "<0.8", false),
1468 ("0.8.1", "<0.8.0", false),
1469 ("0.8.1", "<0.8.1", false),
1470 ("0.8.1", "<0.8.2", true),
1471 ("0.8.1", "<0.9", true),
1472 ("0.8.1", "<0.9.0", true),
1473 ("0.8.1", "<0.9.1", true),
1474 ("0.8.1", "<0.9.2", true),
1475 ("0.8.1", "<=0", true),
1477 ("0.8.1", "<=1", true),
1478 ("0.8.1", "<=1.0", true),
1479 ("0.8.1", "<=1.0.0", true),
1480 ("0.8.1", "<=0.7", false),
1481 ("0.8.1", "<=0.7.0", false),
1482 ("0.8.1", "<=0.7.1", false),
1483 ("0.8.1", "<=0.7.2", false),
1484 ("0.8.1", "<=0.8", true),
1485 ("0.8.1", "<=0.8.0", false),
1486 ("0.8.1", "<=0.8.1", true),
1487 ("0.8.1", "<=0.8.2", true),
1488 ("0.8.1", "<=0.9.0", true),
1489 ("0.8.1", "<=0.9.1", true),
1490 ("0.8.1", "<=0.9.2", true),
1491 ("0.8.1", "~0", true),
1493 ("0.8.1", "~1", false),
1494 ("0.8.1", "~1.0", false),
1495 ("0.8.1", "~1.0.0", false),
1496 ("0.8.1", "~0.7", false),
1497 ("0.8.1", "~0.7.0", false),
1498 ("0.8.1", "~0.7.1", false),
1499 ("0.8.1", "~0.7.2", false),
1500 ("0.8.1", "~0.8", true),
1501 ("0.8.1", "~0.8.0", true),
1502 ("0.8.1", "~0.8.1", true),
1503 ("0.8.1", "~0.8.2", false),
1504 ("0.8.1", "~0.9.0", false),
1505 ("0.8.1", "~0.9.1", false),
1506 ("0.8.1", "~0.9.2", false),
1507 ("0.8.1", "^0", true),
1509 ("0.8.1", "^1", false),
1510 ("0.8.1", "^1.0", false),
1511 ("0.8.1", "^1.0.0", false),
1512 ("0.8.1", "^0.7", false),
1513 ("0.8.1", "^0.7.0", false),
1514 ("0.8.1", "^0.7.1", false),
1515 ("0.8.1", "^0.7.2", false),
1516 ("0.8.1", "^0.8", true),
1517 ("0.8.1", "^0.8.0", true),
1518 ("0.8.1", "^0.8.1", true),
1519 ("0.8.1", "^0.8.2", false),
1520 ("0.8.1", "^0.9.0", false),
1521 ("0.8.1", "^0.9.1", false),
1522 ("0.8.1", "^0.9.2", false),
1523 ("0.8.1", "0 - 1", true),
1525 ("0.8.1", "0.1 - 1.1", true),
1526 ("0.8.1", "0.1.1 - 1.1.1", true),
1527 ("0.8.1", "0 - 0.8.1", true),
1528 ("0.8.1", "0 - 0.8.2", true),
1529 ("0.8.1", "0.7 - 0.8.1", true),
1530 ("0.8.1", "0.7 - 0.8.2", true),
1531 ("0.8.1", "0.8 - 0.8.1", true),
1532 ("0.8.1", "0.8 - 0.8.2", true),
1533 ("0.8.1", "0.8.0 - 0.8.1", true),
1534 ("0.8.1", "0.8.0 - 0.8.2", true),
1535 ("0.8.1", "0.8.0 - 0.9.0", true),
1536 ("0.8.1", "0.8.0 - 1.0.0", true),
1537 ("0.8.1", "0.8.1 - 0.8.1", true),
1538 ("0.8.1", "0.8.1 - 0.8.2", true),
1539 ("0.8.1", "0.8.1 - 0.9.0", true),
1540 ("0.8.1", "0.8.1 - 1.0.0", true),
1541 ("0.8.1", "0.7 - 0.8", true),
1542 ("0.8.1", "0.7.0 - 0.8", true),
1543 ("0.8.1", "0.8 - 0.8", true),
1544 ("0.8.1", "0.8.0 - 0.8", true),
1545 ("0.8.1", "0.8 - 0.8.0", false),
1546 ("0.8.1", "0.8 - 0.8.1", true),
1547 ("0.8.1", "0 || 0", true),
1549 ("0.8.1", "0 || 1", true),
1550 ("0.8.1", "1 || 0", true),
1551 ("0.8.1", "0.0 || 0.0", false),
1552 ("0.8.1", "0.0 || 1.0", false),
1553 ("0.8.1", "1.0 || 0.0", false),
1554 ("0.8.1", "0.7 || 0.8", true),
1555 ("0.8.1", "0.8 || 0.8", true),
1556 ("0.8.1", "0.8 || 0.8.1", true),
1557 ("0.8.1", "0.8 || 0.8.2", true),
1558 ("0.8.1", "0.8 || 0.9", true),
1559 ]);
1560 }
1561}