/
githubmirror
/
sway
Обзор
Документация
Войти
/
githubmirror
/
sway
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
sway-parse/src/parse.rs
165 строк
4 KB
IGI-111
Stabilize ABI errors (#7241)
23 июн 2025, 13:37
Не верифицирован
23 июн 2025, 13:37
5064247
Код
Авторство
О чём код?
use crate::keywords::RESERVED_KEYWORDS; use crate::{ParseResult, Parser, ParserConsumed, Peeker}; use sway_ast::Intrinsic; use sway_error::parser_error::ParseErrorKind; use sway_types::{ast::Delimiter, Ident, Spanned}; pub trait Parse { const FALLBACK_ERROR: ParseErrorKind = ParseErrorKind::InvalidItem; fn parse(parser: &mut Parser) -> ParseResult<Self> where Self: Sized; fn error( #[allow(clippy::boxed_local)] _spans: Box<[sway_types::Span]>, _error: sway_error::handler::ErrorEmitted, ) -> Option<Self> where Self: Sized, { None } } pub trait Peek { fn peek(peeker: Peeker<'_>) -> Option<Self> where Self: Sized; } pub trait ParseToEnd { fn parse_to_end<'a>(parser: Parser<'a, '_>) -> ParseResult<(Self, ParserConsumed<'a>)> where Self: Sized; } impl<T> Parse for Box<T> where T: Parse, { fn parse(parser: &mut Parser) -> ParseResult<Box<T>> { let value = parser.parse()?; Ok(Box::new(value)) } } macro_rules! impl_tuple ( ($($name:ident,)*) => { impl<$($name,)*> Parse for ($($name,)*) where $($name: Parse,)* { #[allow(unused)] fn parse(parser: &mut Parser) -> ParseResult<($($name,)*)> { $( #[allow(non_snake_case)] let $name = parser.parse()?; )* Ok(($($name,)*)) } } impl<$($name,)*> Peek for ($($name,)*) where $($name: Peek,)* { fn peek(peeker: Peeker<'_>) -> Option<Self> { #![allow(unused_assignments, unused, non_snake_case)] let mut tokens = peeker.token_trees; $( let ($name, fewer_tokens) = Peeker::with::<$name>(tokens)?; tokens = fewer_tokens; )* Some(($($name,)*)) } } }; ); impl_tuple!(); impl_tuple!(T0,); impl_tuple!(T0, T1,); impl_tuple!(T0, T1, T2,); impl_tuple!(T0, T1, T2, T3,); impl_tuple!(T0, T1, T2, T3, T4,); impl_tuple!(T0, T1, T2, T3, T4, T5,); impl_tuple!(T0, T1, T2, T3, T4, T5, T6,); impl_tuple!(T0, T1, T2, T3, T4, T5, T6, T7,); impl_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8,); impl_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9,); impl_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10,); impl_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11,); impl<T> ParseToEnd for Vec<T> where T: Parse, { fn parse_to_end<'a, 'e>( mut parser: Parser<'a, '_>, ) -> ParseResult<(Vec<T>, ParserConsumed<'a>)> { let mut ret = Vec::new(); loop { if let Some(consumed) = parser.check_empty() { return Ok((ret, consumed)); } match parser.parse_with_recovery() { Ok(value) => ret.push(value), Err(r) => { let (spans, error) = r.recover_at_next_line_with_fallback_error(T::FALLBACK_ERROR); if let Some(error) = T::error(spans, error) { ret.push(error); } else { Err(error)? } } } } } } impl Peek for Ident { fn peek(peeker: Peeker<'_>) -> Option<Ident> { peeker.peek_ident().ok().cloned() } } impl Parse for Ident { fn parse(parser: &mut Parser) -> ParseResult<Ident> { match parser.take::<Ident>() { Some(ident) => { let ident_str = ident.as_str(); if parser.check_double_underscore && (ident_str.starts_with("__") && Intrinsic::try_from_str(ident_str).is_none()) { return Err(parser.emit_error_with_span( ParseErrorKind::InvalidDoubleUnderscore, ident.span(), )); } if !ident.is_raw_ident() && RESERVED_KEYWORDS.contains(ident_str) { return Err(parser.emit_error_with_span( ParseErrorKind::ReservedKeywordIdentifier, ident.span(), )); } Ok(ident) } None => Err(parser.emit_error(ParseErrorKind::ExpectedIdent)), } } } impl Peek for Delimiter { fn peek(peeker: Peeker<'_>) -> Option<Delimiter> { peeker.peek_delimiter().ok() } }