Skip to content

Commit

Permalink
fix: pragma parsing, add more tests
Browse files Browse the repository at this point in the history
  • Loading branch information
DaniPopes committed May 24, 2024
1 parent 8f13a6f commit 6c7623f
Show file tree
Hide file tree
Showing 12 changed files with 145 additions and 47 deletions.
6 changes: 4 additions & 2 deletions crates/ast/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,9 +327,11 @@ impl TokenKind {
match self {
Eq | Lt | Le | EqEq | Ne | Ge | Gt | AndAnd | OrOr | Not | Tilde | Walrus
| PlusPlus | MinusMinus | StarStar | BinOp(_) | BinOpEq(_) | At | Dot | Comma
| Semi | Colon | Arrow | FatArrow | Question => true,
| Colon | Arrow | FatArrow | Question => true,

OpenDelim(..) | CloseDelim(..) | Literal(..) | Comment(..) | Ident(..) | Eof => false,
OpenDelim(..) | CloseDelim(..) | Literal(..) | Comment(..) | Ident(..) | Semi | Eof => {
false
}
}
}

Expand Down
6 changes: 3 additions & 3 deletions crates/parse/src/lexer/cursor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -265,20 +265,20 @@ impl<'a> Cursor<'a> {
// by field/method access (`12.foo()`)
'.' if !is_id_start(self.second()) => {
self.bump();
let empty_fraction = !self.eat_decimal_digits();
self.eat_decimal_digits();
let empty_exponent = match self.first() {
'e' | 'E' => {
self.bump();
!self.eat_exponent()
}
_ => false,
};
RawLiteralKind::Rational { base, empty_fraction, empty_exponent }
RawLiteralKind::Rational { base, empty_exponent }
}
'e' | 'E' => {
self.bump();
let empty_exponent = !self.eat_exponent();
RawLiteralKind::Rational { base, empty_fraction: false, empty_exponent }
RawLiteralKind::Rational { base, empty_exponent }
}
_ => RawLiteralKind::Int { base, empty_int: false },
}
Expand Down
4 changes: 2 additions & 2 deletions crates/parse/src/lexer/cursor/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,8 @@ pub enum RawTokenKind {
pub enum RawLiteralKind {
/// `123`, `0x123`; empty_int: `0x`
Int { base: Base, empty_int: bool },
/// `123.321`, `1.2e3`; empty_fraction: `1.`, `1.e2`; empty_exponent: `2e`, `2.3e`
Rational { base: Base, empty_fraction: bool, empty_exponent: bool },
/// `123.321`, `1.2e3`; empty_exponent: `2e`, `2.3e`
Rational { base: Base, empty_exponent: bool },
/// `"abc"`, `"abc`; `unicode"abc"`, `unicode"abc`
Str { terminated: bool, unicode: bool },
/// `hex"abc"`, `hex"abc`
Expand Down
7 changes: 1 addition & 6 deletions crates/parse/src/lexer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -345,12 +345,7 @@ impl<'sess, 'src> Lexer<'sess, 'src> {
(TokenLitKind::Integer, self.symbol_from_to(start, end))
}
}
RawLiteralKind::Rational { base, empty_fraction, empty_exponent } => {
if empty_fraction {
let span = self.new_span(start, self.pos);
self.dcx().err("expected at least one digit in fraction").span(span).emit();
}

RawLiteralKind::Rational { base, empty_exponent } => {
if empty_exponent {
let span = self.new_span(start, self.pos);
self.dcx().err("expected at least one digit in exponent").span(span).emit();
Expand Down
26 changes: 18 additions & 8 deletions crates/parse/src/parser/item.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use super::{ExpectedToken, SeqSep};
use crate::{PResult, Parser};
use itertools::Itertools;
use std::num::IntErrorKind;
use sulk_ast::{ast::*, token::*};
use sulk_interface::{error_code, kw, sym, Ident};
use sulk_interface::{error_code, kw, sym, Ident, Span};

impl<'a> Parser<'a> {
/// Parses a source unit.
Expand Down Expand Up @@ -500,8 +501,8 @@ impl<'a> Parser<'a> {
// 0.1 .2
let lit = self.token.lit().unwrap();
let (mj, mn) = lit.symbol.as_str().split_once('.').unwrap();
major = SemverVersionNumber::Number(self.parse_u32(mj)?);
minor = Some(SemverVersionNumber::Number(self.parse_u32(mn)?));
major = SemverVersionNumber::Number(self.parse_u32(mj, self.token.span));
minor = Some(SemverVersionNumber::Number(self.parse_u32(mn, self.token.span)));
self.bump();

patch =
Expand All @@ -514,8 +515,8 @@ impl<'a> Parser<'a> {
// *. 1.2
let lit = self.token.lit().unwrap();
let (mn, p) = lit.symbol.as_str().split_once('.').unwrap();
minor = Some(SemverVersionNumber::Number(self.parse_u32(mn)?));
patch = Some(SemverVersionNumber::Number(self.parse_u32(p)?));
minor = Some(SemverVersionNumber::Number(self.parse_u32(mn, self.token.span)));
patch = Some(SemverVersionNumber::Number(self.parse_u32(p, self.token.span)));
self.bump();
} else {
// *.1 .2
Expand Down Expand Up @@ -548,13 +549,22 @@ impl<'a> Parser<'a> {
self.expected_tokens.push(ExpectedToken::VersionNumber);
return self.unexpected();
};
let value = self.parse_u32(symbol.as_str()).map_err(|e| e.span(span))?;
let value = self.parse_u32(symbol.as_str(), span);
self.bump();
Ok(SemverVersionNumber::Number(value))
}

fn parse_u32(&mut self, s: &str) -> PResult<'a, u32> {
s.parse::<u32>().map_err(|e| self.dcx().err(e.to_string()))
fn parse_u32(&mut self, s: &str, span: Span) -> u32 {
match s.parse::<u32>() {
Ok(n) => n,
Err(e) => match e.kind() {
IntErrorKind::Empty => 0,
_ => {
self.dcx().err(e.to_string()).span(span).emit();
u32::MAX
}
},
}
}

/// Parses an import directive.
Expand Down
2 changes: 0 additions & 2 deletions crates/sema/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,7 @@ impl<'ast, 'sess> Visit<'ast> for AstValidator<'sess> {
if name.name != sym::solidity {
let msg = "only `solidity` is supported as a version pragma";
self.dcx().err(msg).span(name.span).emit();
// return;
}
// TODO: Check or ignore version?
}
ast::PragmaTokens::Custom(name, value) => {
let name = name.as_str();
Expand Down
11 changes: 11 additions & 0 deletions tests/ui/parser/pragma_unknown.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

pragma foo bar;
//~^ ERROR unknown pragma
pragma amogus;
//~^ ERROR unknown pragma
pragma amogus sus;
//~^ ERROR unknown pragma
pragma amogus 69;
//~^ ERROR unknown pragma
pragma amogus 69 diwqbn9ru3b2q945 390ru31290r 0qjr09wadm;
//~^ ERROR unknown pragma
37 changes: 37 additions & 0 deletions tests/ui/parser/pragma_unknown.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
error: unknown pragma
--> $DIR/pragma_unknown.sol:2:1
|
LL | pragma foo bar;
| ^^^^^^^^^^^^^^^
|

error: unknown pragma
--> $DIR/pragma_unknown.sol:4:1
|
LL | pragma amogus;
| ^^^^^^^^^^^^^^
|

error: unknown pragma
--> $DIR/pragma_unknown.sol:6:1
|
LL | pragma amogus sus;
| ^^^^^^^^^^^^^^^^^^
|

error: unknown pragma
--> $DIR/pragma_unknown.sol:8:1
|
LL | pragma amogus 69;
| ^^^^^^^^^^^^^^^^^
|

error: unknown pragma
--> $DIR/pragma_unknown.sol:10:1
|
LL | pragma amogus 69 diwqbn9ru3b2q945 390ru31290r 0qjr09wadm;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|

error: aborting due to 5 previous errors

21 changes: 21 additions & 0 deletions tests/ui/parser/pragma_valid.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
pragma abicoder v1;
pragma abicoder v2;
pragma abicoder "v1";
pragma abicoder "v2";

// These aren't accepted by solc.
pragma "abicoder" v1;
pragma "abicoder" v2;
pragma "abicoder" "v1";
pragma "abicoder" "v2";

pragma experimental ABIEncoderV2;
pragma experimental "ABIEncoderV2";
pragma experimental SMTChecker;
pragma experimental "SMTChecker";

// These aren't accepted by solc.
pragma "experimental" ABIEncoderV2;
pragma "experimental" "ABIEncoderV2";
pragma "experimental" SMTChecker;
pragma "experimental" "SMTChecker";
33 changes: 18 additions & 15 deletions tests/ui/parser/pragmas.sol → tests/ui/parser/pragma_versions.sol
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// Commented out are lexed as empty literals "0."
pragma solidity *.*.*;
pragma solidity *.*.0 ;
pragma solidity *.*.0;
Expand All @@ -7,7 +6,7 @@ pragma solidity *.0 .*;
pragma solidity *.0 .0 ;
pragma solidity *.0 .0;
pragma solidity *.0 ;
// pragma solidity *.0.*;
pragma solidity *.0.*;
pragma solidity *.0.0 ;
pragma solidity *.0.0;
pragma solidity *.0;
Expand All @@ -20,15 +19,15 @@ pragma solidity 0 .0 .*;
pragma solidity 0 .0 .0 ;
pragma solidity 0 .0 .0;
pragma solidity 0 .0 ;
// pragma solidity 0 .0.*;
pragma solidity 0 .0.*;
pragma solidity 0 .0.0 ;
pragma solidity 0 .0.0;
pragma solidity 0 .0;
pragma solidity 0 ;
// pragma solidity 0.*.*;
// pragma solidity 0.*.0 ;
// pragma solidity 0.*.0;
// pragma solidity 0.*;
pragma solidity 0.*.*;
pragma solidity 0.*.0 ;
pragma solidity 0.*.0;
pragma solidity 0.*;
pragma solidity 0.0 .*;
pragma solidity 0.0 .0 ;
pragma solidity 0.0 .0;
Expand All @@ -39,13 +38,17 @@ pragma solidity 0.0.0;
pragma solidity 0.0;
pragma solidity 0;

// pragma foo bar;
// ~^ ERROR unknown pragma
pragma abicoder v2;
// pragma solidity ^4294967295;
// ~^ ERROR too large
pragma solidity 0 - 1 0 - 2;
//~^ ERROR ranges can only be combined using the || operator
pragma abicoder "v2";
pragma solidity ^0.5.16 =0.8.22 || >=0.8.21 <=2 ~1 0.6.2;
pragma solidity 0.4 - 1 || 0.3 - 0.5.16;

pragma solidity ^4294967295;
pragma solidity ^4294967296;
//~^ ERROR too large
pragma solidity ^0.4294967296;
//~^ ERROR too large

pragma solidity 88_;
//~^ ERROR invalid digit

pragma solidity 0 - 1 0 - 2;
//~^ ERROR ranges can only be combined using the || operator
30 changes: 30 additions & 0 deletions tests/ui/parser/pragma_versions.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
error: number too large to fit in target type
--> $DIR/pragma_versions.sol:45:18
|
LL | pragma solidity ^4294967296;
| ^^^^^^^^^^
|

error: number too large to fit in target type
--> $DIR/pragma_versions.sol:47:18
|
LL | pragma solidity ^0.4294967296;
| ^^^^^^^^^^^^
|

error: invalid digit found in string
--> $DIR/pragma_versions.sol:50:17
|
LL | pragma solidity 88_;
| ^^^
|

error: ranges can only be combined using the || operator
--> $DIR/pragma_versions.sol:53:1
|
LL | pragma solidity 0 - 1 0 - 2;
| ^^^^^^^^^^^^^^^^^^^^^
|

error: aborting due to 4 previous errors

9 changes: 0 additions & 9 deletions tests/ui/parser/pragmas.stderr

This file was deleted.

0 comments on commit 6c7623f

Please sign in to comment.