2023-10-17 18:36:21 +00:00
|
|
|
//! Parses [tokens](super::token) into an [AST](super::ast)
|
2024-01-21 07:34:40 +00:00
|
|
|
#![deprecated]
|
|
|
|
#![allow(deprecated)]
|
2023-10-24 00:43:16 +00:00
|
|
|
use super::{ast::preamble::*, lexer::Lexer, token::preamble::*};
|
2024-01-04 08:18:09 +00:00
|
|
|
use error::{Error, *};
|
2023-10-17 18:36:21 +00:00
|
|
|
|
2023-10-20 20:33:02 +00:00
|
|
|
pub mod error {
|
2023-10-17 18:36:21 +00:00
|
|
|
use super::{Token, Type};
|
2023-10-20 20:33:02 +00:00
|
|
|
use std::fmt::Display;
|
2023-10-17 18:36:21 +00:00
|
|
|
|
2024-01-04 08:18:09 +00:00
|
|
|
pub trait WrapError {
|
|
|
|
/// Wraps this error in a parent [Error]
|
|
|
|
fn wrap(self, parent: Error) -> Self;
|
|
|
|
}
|
|
|
|
impl WrapError for Error {
|
|
|
|
fn wrap(self, parent: Error) -> Self {
|
|
|
|
Self { child: Some(self.into()), ..parent }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
impl<T> WrapError for Result<T, Error> {
|
|
|
|
fn wrap(self, parent: Error) -> Self {
|
|
|
|
self.map_err(|e| e.wrap(parent))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-26 19:41:59 +00:00
|
|
|
/// The reason for the [Error]
|
2023-10-29 06:13:48 +00:00
|
|
|
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
2023-10-17 18:36:21 +00:00
|
|
|
pub enum Reason {
|
|
|
|
Expected(Type),
|
2023-10-22 23:28:20 +00:00
|
|
|
Unexpected(Type),
|
2024-01-04 08:18:09 +00:00
|
|
|
NotPathSegment(Type),
|
2023-10-17 18:36:21 +00:00
|
|
|
NotIdentifier,
|
2024-01-04 08:18:09 +00:00
|
|
|
NotStatement,
|
|
|
|
NotLet,
|
|
|
|
NotFnDecl,
|
2023-10-21 17:24:52 +00:00
|
|
|
NotOperator,
|
2023-10-17 18:36:21 +00:00
|
|
|
NotLiteral,
|
|
|
|
NotString,
|
2023-10-19 19:40:03 +00:00
|
|
|
NotChar,
|
2023-10-17 18:36:21 +00:00
|
|
|
NotBool,
|
|
|
|
NotFloat,
|
2023-10-21 17:24:52 +00:00
|
|
|
NotInt,
|
2023-10-17 18:36:21 +00:00
|
|
|
FloatExponentOverflow,
|
|
|
|
FloatMantissaOverflow,
|
|
|
|
IntOverflow,
|
|
|
|
NotBranch,
|
2023-10-21 17:24:52 +00:00
|
|
|
IncompleteBranch,
|
2023-10-17 18:36:21 +00:00
|
|
|
EndOfFile,
|
2023-10-21 17:24:52 +00:00
|
|
|
PanicStackUnderflow,
|
2023-10-17 18:36:21 +00:00
|
|
|
#[default]
|
|
|
|
Unspecified,
|
|
|
|
}
|
|
|
|
use Reason::*;
|
2023-10-20 20:33:02 +00:00
|
|
|
|
|
|
|
impl Display for Reason {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
match self {
|
|
|
|
Self::Expected(t) => write!(f, "Expected {t}"),
|
2023-10-22 23:28:20 +00:00
|
|
|
Self::Unexpected(t) => write!(f, "Unexpected {t} in bagging area"),
|
2024-01-04 08:18:09 +00:00
|
|
|
Self::NotPathSegment(t) => write!(f, "{t} not a path segment"),
|
2023-10-21 17:24:52 +00:00
|
|
|
Self::NotIdentifier => "Not an identifier".fmt(f),
|
2024-01-04 08:18:09 +00:00
|
|
|
Self::NotStatement => "Not a statement".fmt(f),
|
|
|
|
Self::NotLet => "Not a let statement".fmt(f),
|
|
|
|
Self::NotFnDecl => "Not a valid function declaration".fmt(f),
|
2023-10-21 17:24:52 +00:00
|
|
|
Self::NotOperator => "Not an operator".fmt(f),
|
|
|
|
Self::NotLiteral => "Not a literal".fmt(f),
|
|
|
|
Self::NotString => "Not a string".fmt(f),
|
|
|
|
Self::NotChar => "Not a char".fmt(f),
|
|
|
|
Self::NotBool => "Not a bool".fmt(f),
|
|
|
|
Self::NotFloat => "Not a float".fmt(f),
|
|
|
|
Self::FloatExponentOverflow => "Float exponent too large".fmt(f),
|
|
|
|
Self::FloatMantissaOverflow => "Float mantissa too large".fmt(f),
|
|
|
|
Self::NotInt => "Not an integer".fmt(f),
|
|
|
|
Self::IntOverflow => "Integer too large".fmt(f),
|
|
|
|
Self::IncompleteBranch => "Branch expression was incomplete".fmt(f),
|
|
|
|
Self::NotBranch => "Expected branch expression".fmt(f),
|
|
|
|
Self::EndOfFile => "Got end of file".fmt(f),
|
|
|
|
Self::PanicStackUnderflow => "Could not recover from panic".fmt(f),
|
|
|
|
Self::Unspecified => {
|
|
|
|
"Unspecified error. You are permitted to slap the code author.".fmt(f)
|
|
|
|
}
|
2023-10-20 20:33:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-21 17:24:52 +00:00
|
|
|
/// [Parser](super::Parser) [Result]
|
2023-10-17 18:36:21 +00:00
|
|
|
pub type PResult<T> = Result<T, Error>;
|
2023-10-26 19:41:59 +00:00
|
|
|
/// An error produced by the [Parser](super::Parser).
|
|
|
|
///
|
|
|
|
/// Contains a [Reason], and, optionally, a start [Token]
|
2023-10-22 23:28:20 +00:00
|
|
|
#[derive(Clone, Debug, Default, PartialEq)]
|
2023-10-17 18:36:21 +00:00
|
|
|
pub struct Error {
|
|
|
|
reason: Reason,
|
2024-01-04 08:18:09 +00:00
|
|
|
child: Option<Box<Self>>,
|
2023-10-17 18:36:21 +00:00
|
|
|
start: Option<Token>,
|
|
|
|
}
|
2023-10-26 19:48:44 +00:00
|
|
|
impl std::error::Error for Error {}
|
2023-10-20 20:33:02 +00:00
|
|
|
impl Display for Error {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
2024-01-04 08:18:09 +00:00
|
|
|
if let Some(child) = &self.child {
|
|
|
|
write!(f, "{child}: ")?;
|
|
|
|
}
|
2023-10-22 23:28:20 +00:00
|
|
|
if let Some(token) = &self.start {
|
2023-10-20 20:33:02 +00:00
|
|
|
write!(f, "{}:{}: ", token.line(), token.col())?;
|
|
|
|
}
|
|
|
|
write!(f, "{}", self.reason)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-17 18:36:21 +00:00
|
|
|
macro error_impl($($fn:ident$(($($p:ident: $t:ty),*))?: $reason:expr),*$(,)?) {$(
|
2023-10-24 04:43:11 +00:00
|
|
|
/// Creates an [Error] with this [Reason]:
|
|
|
|
#[doc = concat!("[`", stringify!($reason), "`]")]
|
|
|
|
#[allow(dead_code)]
|
|
|
|
pub(crate) fn $fn($($($p : $t),*)?) -> Self {
|
2024-01-04 08:18:09 +00:00
|
|
|
Self { reason: $reason$(($($p)*))?, child: None, start: None }
|
2023-10-19 19:40:03 +00:00
|
|
|
}
|
|
|
|
)*}
|
2023-10-17 18:36:21 +00:00
|
|
|
impl Error {
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Provides an optional start [Token]
|
2023-10-17 18:36:21 +00:00
|
|
|
pub fn token(self, start: Token) -> Self {
|
|
|
|
Self { start: Some(start), ..self }
|
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Optionally sets the start [Token]
|
2023-10-19 19:40:03 +00:00
|
|
|
pub fn maybe_token(self, start: Option<Token>) -> Self {
|
|
|
|
Self { start, ..self }
|
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Gets a reference to the start [Token], if there is one
|
2023-10-22 23:28:20 +00:00
|
|
|
pub fn start(&self) -> Option<&Token> {
|
|
|
|
self.start.as_ref()
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Gets the [Reason] for this error
|
2023-10-29 06:13:48 +00:00
|
|
|
pub fn reason(&self) -> Reason {
|
|
|
|
self.reason
|
|
|
|
}
|
2023-10-17 18:36:21 +00:00
|
|
|
error_impl! {
|
|
|
|
expected(e: Type): Expected,
|
2023-10-22 23:28:20 +00:00
|
|
|
unexpected(e: Type): Unexpected,
|
2024-01-04 08:18:09 +00:00
|
|
|
not_path_segment(e: Type): NotPathSegment,
|
2023-10-17 18:36:21 +00:00
|
|
|
not_identifier: NotIdentifier,
|
2024-01-04 08:18:09 +00:00
|
|
|
not_statement: NotStatement,
|
|
|
|
not_let: NotLet,
|
|
|
|
not_fn_decl: NotFnDecl,
|
2023-10-21 17:24:52 +00:00
|
|
|
not_operator: NotOperator,
|
2023-10-17 18:36:21 +00:00
|
|
|
not_literal: NotLiteral,
|
|
|
|
not_string: NotString,
|
2023-10-19 19:40:03 +00:00
|
|
|
not_char: NotChar,
|
2023-10-17 18:36:21 +00:00
|
|
|
not_bool: NotBool,
|
|
|
|
not_float: NotFloat,
|
|
|
|
float_exponent_overflow: FloatExponentOverflow,
|
|
|
|
float_mantissa_overflow: FloatMantissaOverflow,
|
|
|
|
not_int: NotInt,
|
|
|
|
int_overflow: IntOverflow,
|
|
|
|
not_branch: NotBranch,
|
|
|
|
end_of_file: EndOfFile,
|
2023-10-21 17:24:52 +00:00
|
|
|
panic_underflow: PanicStackUnderflow,
|
2023-10-17 18:36:21 +00:00
|
|
|
unspecified: Unspecified,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The Parser performs recursive descent on the AST's grammar
|
|
|
|
/// using a provided [Lexer].
|
2023-10-22 23:28:20 +00:00
|
|
|
pub struct Parser {
|
2023-10-17 18:36:21 +00:00
|
|
|
tokens: Vec<Token>,
|
|
|
|
panic_stack: Vec<usize>,
|
2023-10-29 06:13:48 +00:00
|
|
|
pub errors: Vec<Error>,
|
2023-10-26 19:41:59 +00:00
|
|
|
cursor: usize,
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
2023-10-22 23:28:20 +00:00
|
|
|
impl<'t> From<Lexer<'t>> for Parser {
|
2023-10-17 18:36:21 +00:00
|
|
|
fn from(value: Lexer<'t>) -> Self {
|
2023-10-22 23:28:20 +00:00
|
|
|
let mut tokens = vec![];
|
|
|
|
for result in value {
|
|
|
|
match result {
|
|
|
|
Ok(t) => tokens.push(t),
|
|
|
|
Err(e) => println!("{e}"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Self::new(tokens)
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-10-22 23:28:20 +00:00
|
|
|
impl Parser {
|
2023-10-17 18:36:21 +00:00
|
|
|
/// Create a new [Parser] from a list of [Tokens][1]
|
|
|
|
/// and the [text](str) used to generate that list
|
|
|
|
/// (as [Tokens][1] do not store their strings)
|
|
|
|
///
|
|
|
|
/// [1]: Token
|
2023-10-22 23:28:20 +00:00
|
|
|
pub fn new(tokens: Vec<Token>) -> Self {
|
2023-10-29 06:13:48 +00:00
|
|
|
Self { tokens, panic_stack: vec![], errors: vec![], cursor: 0 }
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
2024-01-04 08:18:09 +00:00
|
|
|
/// Resets the parser, so it can be reused
|
|
|
|
pub fn reset(&mut self) -> &mut Self {
|
|
|
|
*self = Self::new(std::mem::take(&mut self.tokens));
|
|
|
|
self
|
|
|
|
}
|
2023-10-26 19:33:56 +00:00
|
|
|
/// Parses the [start of an AST](Start)
|
2023-10-20 20:33:02 +00:00
|
|
|
pub fn parse(&mut self) -> PResult<Start> {
|
|
|
|
self.consume_comments();
|
2023-10-26 19:33:56 +00:00
|
|
|
Ok(Start(self.program()?))
|
|
|
|
}
|
|
|
|
/// Parses only one expression
|
2024-01-04 08:18:09 +00:00
|
|
|
pub fn parse_expr(&mut self) -> PResult<Expr> {
|
2023-10-26 19:33:56 +00:00
|
|
|
self.expr()
|
2023-10-20 20:33:02 +00:00
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Peeks at the current token
|
|
|
|
pub fn peek(&self) -> PResult<&Token> {
|
|
|
|
self.tokens
|
|
|
|
.get(self.cursor)
|
2024-01-04 08:18:09 +00:00
|
|
|
.ok_or_else(|| Error::end_of_file().maybe_token(self.tokens.last().cloned()))
|
2023-10-26 19:41:59 +00:00
|
|
|
}
|
|
|
|
/// Consumes any number of consecutive comments
|
2023-10-17 18:36:21 +00:00
|
|
|
fn consume_comments(&mut self) -> &mut Self {
|
2023-10-20 20:33:02 +00:00
|
|
|
while let Ok(Type::Comment) = self.peek().map(|t| t.ty()) {
|
2023-10-26 19:41:59 +00:00
|
|
|
self.cursor += 1;
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
|
|
|
self
|
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Consumes the current token
|
2023-10-17 18:36:21 +00:00
|
|
|
#[inline]
|
2023-10-24 04:43:11 +00:00
|
|
|
fn consume(&mut self) -> &mut Self {
|
2023-10-26 19:41:59 +00:00
|
|
|
self.cursor += 1;
|
2023-10-17 18:36:21 +00:00
|
|
|
self.consume_comments();
|
|
|
|
self
|
|
|
|
}
|
2023-10-29 06:13:48 +00:00
|
|
|
}
|
|
|
|
/// Panicking
|
|
|
|
#[allow(dead_code)]
|
|
|
|
impl Parser {
|
2023-10-17 18:36:21 +00:00
|
|
|
/// Records the current position on the panic stack
|
2023-10-24 04:43:11 +00:00
|
|
|
fn mark(&mut self) -> &mut Self {
|
2023-10-26 19:41:59 +00:00
|
|
|
self.panic_stack.push(self.cursor);
|
2023-10-17 18:36:21 +00:00
|
|
|
self
|
|
|
|
}
|
|
|
|
/// Erases a recorded position from the panic stack
|
2023-10-24 04:43:11 +00:00
|
|
|
fn unmark(&mut self) -> &mut Self {
|
2023-10-17 18:36:21 +00:00
|
|
|
self.panic_stack.pop();
|
|
|
|
self
|
|
|
|
}
|
|
|
|
/// Unwinds the panic stack one step
|
2023-10-24 04:43:11 +00:00
|
|
|
fn unwind(&mut self) -> PResult<&mut Self> {
|
2023-10-21 17:24:52 +00:00
|
|
|
let v = self.panic_stack.pop().ok_or(Error::panic_underflow())?;
|
2023-10-26 19:41:59 +00:00
|
|
|
self.cursor = v;
|
2023-10-21 17:24:52 +00:00
|
|
|
Ok(self)
|
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Advances forward until a token with type [`t`](Type) is encountered
|
2023-10-24 04:43:11 +00:00
|
|
|
fn advance_until(&mut self, t: Type) -> PResult<&mut Self> {
|
2023-10-21 17:24:52 +00:00
|
|
|
while self.matches(t).is_err() {
|
2024-01-04 08:18:09 +00:00
|
|
|
self.check_eof().wrap(Error::expected(t))?.consume();
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
2023-10-21 17:24:52 +00:00
|
|
|
Ok(self)
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
2023-10-29 06:13:48 +00:00
|
|
|
/// Marks the current position, and unwinds the panic stack if `f` fails.
|
|
|
|
fn attempt<F, R>(&mut self, f: F) -> PResult<R>
|
|
|
|
where F: FnOnce(&mut Self) -> PResult<R> {
|
|
|
|
self.mark();
|
|
|
|
let out = f(self);
|
|
|
|
match out {
|
|
|
|
Ok(_) => self.unmark(),
|
|
|
|
Err(_) => self.unwind()?,
|
|
|
|
};
|
|
|
|
out
|
|
|
|
}
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
|
|
|
/// Helpers
|
2023-10-22 23:28:20 +00:00
|
|
|
impl Parser {
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Returns an error if the end of input has been reached
|
2023-10-17 18:36:21 +00:00
|
|
|
fn check_eof(&mut self) -> PResult<&mut Self> {
|
2023-10-26 19:41:59 +00:00
|
|
|
if self.cursor < self.tokens.len() {
|
2023-10-17 18:36:21 +00:00
|
|
|
Ok(self)
|
|
|
|
} else {
|
2023-10-22 23:28:20 +00:00
|
|
|
Err(Error::end_of_file().maybe_token(self.tokens.last().cloned()))
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Peeks at the next token if it has the expected [Type]
|
|
|
|
fn matches(&mut self, t: Type) -> PResult<&Token> {
|
|
|
|
let token = self.check_eof()?.peek().expect("self should not be eof");
|
|
|
|
if token.ty() != t {
|
2024-01-04 08:18:09 +00:00
|
|
|
Err(Error::expected(t).token(token.clone()))
|
|
|
|
} else {
|
|
|
|
Ok(token)
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Consumes, without returning, a token with the given [Keyword], or returns an error.
|
2023-10-27 05:19:19 +00:00
|
|
|
///
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Useful if you only want to check the existence of a [Keyword]
|
2023-10-17 18:36:21 +00:00
|
|
|
fn keyword(&mut self, keyword: Keyword) -> PResult<&mut Self> {
|
|
|
|
self.consume_type(Type::Keyword(keyword))
|
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Consumes, without returning, a token with the given [Type], or returns an error.
|
2023-10-27 05:19:19 +00:00
|
|
|
///
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Useful if you only want to check the existence of a token.
|
|
|
|
fn consume_type(&mut self, t: Type) -> PResult<&mut Self> {
|
|
|
|
self.matches(t)?;
|
|
|
|
Ok(self.consume())
|
|
|
|
}
|
|
|
|
#[doc(hidden)]
|
|
|
|
fn todo_error(&mut self, l: u32, c: u32, s: &str) -> Error {
|
|
|
|
eprintln!("TODO: {s}:{l}:{c}");
|
|
|
|
Error::unspecified().token(self.peek().unwrap().clone())
|
|
|
|
}
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// TODO: Remove `ptodo*`
|
2023-10-17 18:36:21 +00:00
|
|
|
macro ptodo_err($self:expr $(, $t:expr)*) {
|
|
|
|
$($t;)*
|
|
|
|
$self.todo_error(line!(), column!(), file!())
|
|
|
|
}
|
|
|
|
macro ptodo($self:expr $(, $t:expr)*) {
|
|
|
|
$($t;)*
|
|
|
|
Err(ptodo_err!($self))
|
|
|
|
}
|
|
|
|
|
|
|
|
/// # Terminals and Pseudo-Terminals
|
2023-10-22 23:28:20 +00:00
|
|
|
impl Parser {
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Parses an [Identifier]
|
2023-10-21 17:24:52 +00:00
|
|
|
fn identifier(&mut self) -> PResult<Identifier> {
|
2023-10-22 23:28:20 +00:00
|
|
|
let out = match self.matches(Type::Identifier)?.data() {
|
2024-01-04 08:18:09 +00:00
|
|
|
Data::Identifier(id) => Identifier { name: id.to_string(), index: None },
|
2023-10-22 23:28:20 +00:00
|
|
|
_ => Err(Error::not_identifier())?,
|
|
|
|
};
|
|
|
|
self.consume();
|
|
|
|
Ok(out)
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Parses a [Literal](literal::Literal)
|
2023-10-21 17:24:52 +00:00
|
|
|
fn literal(&mut self) -> PResult<literal::Literal> {
|
2023-10-17 18:36:21 +00:00
|
|
|
use literal::Literal::*;
|
|
|
|
use Keyword::{False, True};
|
2023-10-22 23:28:20 +00:00
|
|
|
let token = self.peek()?;
|
|
|
|
match token.ty() {
|
2023-10-17 18:36:21 +00:00
|
|
|
Type::Float => self.float().map(Float),
|
2023-10-21 17:24:52 +00:00
|
|
|
Type::Integer => self.int().map(Int),
|
2023-10-17 18:36:21 +00:00
|
|
|
Type::String => self.string().map(String),
|
|
|
|
Type::Character => self.char().map(Char),
|
|
|
|
Type::Keyword(True | False) => self.bool().map(Bool),
|
2023-10-22 23:28:20 +00:00
|
|
|
_ => Err(Error::not_literal().token(token.clone())),
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Parses a [floating point literal](literal::Float)
|
2023-10-21 17:24:52 +00:00
|
|
|
fn float(&mut self) -> PResult<literal::Float> {
|
2023-10-17 18:36:21 +00:00
|
|
|
ptodo!(self)
|
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Parses an [integer literal](u128)
|
|
|
|
///
|
|
|
|
/// u128 was chosen for this, since it stores the largest integer precision Rust natively
|
|
|
|
/// supports. Conlang doesn't currently plan to support arbitrary-width arithmetic anyway.
|
2023-10-21 17:24:52 +00:00
|
|
|
fn int(&mut self) -> PResult<u128> {
|
2023-10-22 23:28:20 +00:00
|
|
|
let out = match self.matches(Type::Integer)?.data() {
|
2023-10-24 00:43:16 +00:00
|
|
|
Data::Integer(i) => *i,
|
2023-10-22 23:28:20 +00:00
|
|
|
_ => Err(Error::not_int())?,
|
|
|
|
};
|
|
|
|
self.consume();
|
|
|
|
Ok(out)
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Parses a [string literal](String)
|
2023-10-21 17:24:52 +00:00
|
|
|
fn string(&mut self) -> PResult<String> {
|
2023-10-22 23:28:20 +00:00
|
|
|
let out = match self.matches(Type::String)?.data() {
|
2023-10-24 00:43:16 +00:00
|
|
|
Data::String(s) => s.clone(),
|
2023-10-22 23:28:20 +00:00
|
|
|
_ => Err(Error::not_string())?,
|
|
|
|
};
|
|
|
|
self.consume();
|
|
|
|
Ok(out)
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Parses a [character literal](char)
|
2023-10-21 17:24:52 +00:00
|
|
|
fn char(&mut self) -> PResult<char> {
|
2023-10-22 23:28:20 +00:00
|
|
|
let out = match self.matches(Type::Character)?.data() {
|
2023-10-24 00:43:16 +00:00
|
|
|
Data::Character(c) => *c,
|
2023-10-22 23:28:20 +00:00
|
|
|
_ => Err(Error::not_char())?,
|
|
|
|
};
|
|
|
|
self.consume();
|
|
|
|
Ok(out)
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Parses a [boolean literal](bool)
|
2023-10-21 17:24:52 +00:00
|
|
|
fn bool(&mut self) -> PResult<bool> {
|
2023-10-17 18:36:21 +00:00
|
|
|
use Keyword::{False, True};
|
2023-10-20 20:33:02 +00:00
|
|
|
let token = self.peek()?;
|
2023-10-17 18:36:21 +00:00
|
|
|
let out = match token.ty() {
|
|
|
|
Type::Keyword(False) => false,
|
|
|
|
Type::Keyword(True) => true,
|
2023-10-22 23:28:20 +00:00
|
|
|
_ => Err(Error::not_bool().token(token.clone()))?,
|
2023-10-17 18:36:21 +00:00
|
|
|
};
|
|
|
|
self.consume();
|
|
|
|
Ok(out)
|
|
|
|
}
|
|
|
|
}
|
2023-10-26 19:33:56 +00:00
|
|
|
/// Statements
|
|
|
|
impl Parser {
|
|
|
|
/// Parses a series of [statements](Stmt)
|
|
|
|
fn program(&mut self) -> PResult<Program> {
|
|
|
|
let mut out = vec![];
|
|
|
|
while self.check_eof().is_ok() {
|
|
|
|
out.push(self.stmt()?);
|
|
|
|
}
|
|
|
|
Ok(Program(out))
|
|
|
|
}
|
|
|
|
/// Parses a single [statement](Stmt)
|
|
|
|
fn stmt(&mut self) -> PResult<Stmt> {
|
|
|
|
let token = self.peek()?;
|
|
|
|
match token.ty() {
|
2024-01-04 08:18:09 +00:00
|
|
|
Type::Keyword(Keyword::Let) => self.let_stmt().map(Stmt::Let).wrap(Error::not_let()),
|
|
|
|
Type::Keyword(Keyword::Fn) => self.fn_decl().map(Stmt::Fn).wrap(Error::not_fn_decl()),
|
2023-10-26 19:33:56 +00:00
|
|
|
_ => {
|
|
|
|
let out = Stmt::Expr(self.expr()?);
|
|
|
|
self.consume_type(Type::Semi)?;
|
|
|
|
Ok(out)
|
|
|
|
}
|
|
|
|
}
|
2024-01-04 08:18:09 +00:00
|
|
|
.wrap(Error::not_statement())
|
2023-10-26 19:33:56 +00:00
|
|
|
}
|
2023-10-29 06:13:48 +00:00
|
|
|
/// Parses a [Let] statement
|
|
|
|
fn let_stmt(&mut self) -> PResult<Let> {
|
2024-01-04 08:18:09 +00:00
|
|
|
self.keyword(Keyword::Let)?;
|
|
|
|
let out =
|
|
|
|
Let { name: self.name()?, init: self.consume_type(Type::Eq).and_then(Self::expr).ok() };
|
2023-10-29 06:13:48 +00:00
|
|
|
self.consume_type(Type::Semi)?;
|
|
|
|
Ok(out)
|
|
|
|
}
|
2024-01-04 08:18:09 +00:00
|
|
|
/// Parses a [function declaration](FnDecl) statement
|
2023-10-30 04:47:00 +00:00
|
|
|
fn fn_decl(&mut self) -> PResult<FnDecl> {
|
|
|
|
self.keyword(Keyword::Fn)?;
|
|
|
|
let name = self.identifier()?;
|
|
|
|
self.consume_type(Type::LParen)?;
|
|
|
|
let args = self.params()?;
|
|
|
|
self.consume_type(Type::RParen)?;
|
2023-10-30 05:07:27 +00:00
|
|
|
// TODO: Parse type-expressions and store return types in the AST
|
2024-01-04 08:18:09 +00:00
|
|
|
let ty = if self.consume_type(Type::Arrow).is_ok() {
|
|
|
|
Some(self.type_expr()?)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
2024-01-05 23:48:19 +00:00
|
|
|
Ok(FnDecl { name: Name { symbol: name, mutable: false, ty }, args, body: self.block()? })
|
2024-01-04 08:18:09 +00:00
|
|
|
}
|
|
|
|
/// Parses a [parameter](Name) list for [FnDecl]
|
|
|
|
fn params(&mut self) -> PResult<Vec<Name>> {
|
|
|
|
let mut args = vec![];
|
|
|
|
while let Ok(name) = self.name() {
|
|
|
|
args.push(name);
|
|
|
|
if self.consume_type(Type::Comma).is_err() {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(args)
|
|
|
|
}
|
|
|
|
/// Parses a [Name]; the object of a let statement, or a single function parameter.
|
|
|
|
fn name(&mut self) -> PResult<Name> {
|
|
|
|
Ok(Name {
|
|
|
|
mutable: self.keyword(Keyword::Mut).is_ok(),
|
2024-01-05 23:48:19 +00:00
|
|
|
symbol: self.identifier()?,
|
2024-01-04 08:18:09 +00:00
|
|
|
ty: self
|
|
|
|
.consume_type(Type::Colon)
|
|
|
|
.and_then(|this| this.type_expr())
|
|
|
|
.ok(),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// Path Expressions
|
|
|
|
impl Parser {
|
|
|
|
fn path(&mut self) -> PResult<path::Path> {
|
|
|
|
let absolute = self.consume_type(Type::ColonColon).is_ok();
|
|
|
|
let mut parts = vec![];
|
|
|
|
while let Ok(id) = self.path_part() {
|
|
|
|
parts.push(id);
|
|
|
|
if self.consume_type(Type::ColonColon).is_err() {
|
|
|
|
break;
|
|
|
|
}
|
2023-10-30 04:47:00 +00:00
|
|
|
}
|
2024-01-04 08:18:09 +00:00
|
|
|
Ok(Path { absolute, parts })
|
2023-10-30 04:47:00 +00:00
|
|
|
}
|
|
|
|
|
2024-01-04 08:18:09 +00:00
|
|
|
fn path_part(&mut self) -> PResult<PathPart> {
|
|
|
|
match self.peek()?.ty() {
|
|
|
|
Type::Identifier => self.identifier().map(PathPart::PathIdent),
|
|
|
|
Type::Keyword(Keyword::Super) => {
|
|
|
|
self.keyword(Keyword::Super).map(|_| PathPart::PathSuper)
|
2023-10-30 05:07:27 +00:00
|
|
|
}
|
2024-01-04 08:18:09 +00:00
|
|
|
Type::Keyword(Keyword::SelfKw) => {
|
|
|
|
self.keyword(Keyword::SelfKw).map(|_| PathPart::PathSelf)
|
|
|
|
}
|
2024-01-05 23:48:19 +00:00
|
|
|
e => Err(Error::not_path_segment(e)),
|
2024-01-04 08:18:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// Type Expressions
|
|
|
|
impl Parser {
|
|
|
|
/// Parses a [Type Expression](TypeExpr)
|
|
|
|
fn type_expr(&mut self) -> PResult<TypeExpr> {
|
|
|
|
match self.peek()?.ty() {
|
|
|
|
Type::LParen => self.type_tuple().map(TypeExpr::TupleType),
|
|
|
|
Type::Bang => self.type_never().map(TypeExpr::Never),
|
|
|
|
_ => self.path().map(TypeExpr::TypePath),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
fn type_tuple(&mut self) -> PResult<TupleType> {
|
|
|
|
self.consume_type(Type::LParen)?;
|
|
|
|
let mut types = vec![];
|
|
|
|
while let Ok(ty) = self.type_expr() {
|
|
|
|
types.push(ty);
|
2023-10-30 04:47:00 +00:00
|
|
|
if self.consume_type(Type::Comma).is_err() {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2024-01-04 08:18:09 +00:00
|
|
|
self.consume_type(Type::RParen)?;
|
|
|
|
Ok(TupleType { types })
|
|
|
|
}
|
|
|
|
fn type_never(&mut self) -> PResult<Never> {
|
|
|
|
self.consume_type(Type::Bang).map(|_| Never)
|
2023-10-30 04:47:00 +00:00
|
|
|
}
|
2023-10-26 19:33:56 +00:00
|
|
|
}
|
2024-01-04 08:18:09 +00:00
|
|
|
|
2023-10-17 18:36:21 +00:00
|
|
|
/// Expressions
|
2023-10-22 23:28:20 +00:00
|
|
|
impl Parser {
|
2024-01-04 08:18:09 +00:00
|
|
|
/// Parses an [expression](Expr)
|
|
|
|
fn expr(&mut self) -> PResult<Expr> {
|
2023-10-27 05:19:19 +00:00
|
|
|
Ok(Expr(self.assign()?))
|
2023-10-19 19:40:03 +00:00
|
|
|
}
|
2024-01-04 08:18:09 +00:00
|
|
|
/// Parses a [block expression](Block)
|
|
|
|
fn block(&mut self) -> PResult<Block> {
|
2023-10-29 06:13:48 +00:00
|
|
|
let mut statements = vec![];
|
|
|
|
let mut expr: Option<Box<Expr>> = None;
|
|
|
|
self.consume_type(Type::LCurly)?;
|
|
|
|
// tHeRe Is No PlAcE iN yOuR gRaMmAr WhErE bOtH aN eXpReSsIoN aNd A sTaTeMeNt ArE eXpEcTeD
|
|
|
|
while self.consume_type(Type::RCurly).is_err() {
|
|
|
|
match self.expr() {
|
|
|
|
Ok(e) if self.consume_type(Type::Semi).is_ok() => statements.push(Stmt::Expr(e)),
|
|
|
|
Ok(e) => {
|
|
|
|
expr = Some(Box::new(e));
|
|
|
|
self.consume_type(Type::RCurly)?;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
Err(_) => statements.push(self.stmt()?),
|
|
|
|
}
|
|
|
|
}
|
2024-01-04 08:18:09 +00:00
|
|
|
Ok(Block { statements, expr, let_count: None })
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
2024-01-04 08:18:09 +00:00
|
|
|
/// Parses a [primary expression](Primary)
|
|
|
|
fn primary(&mut self) -> PResult<Primary> {
|
2023-10-22 23:28:20 +00:00
|
|
|
let token = self.peek()?;
|
2023-10-21 17:24:52 +00:00
|
|
|
match token.ty() {
|
|
|
|
Type::Identifier => self.identifier().map(Primary::Identifier),
|
|
|
|
Type::String
|
|
|
|
| Type::Character
|
|
|
|
| Type::Integer
|
|
|
|
| Type::Float
|
|
|
|
| Type::Keyword(Keyword::True | Keyword::False) => self.literal().map(Primary::Literal),
|
|
|
|
Type::LCurly => self.block().map(Primary::Block),
|
|
|
|
Type::LParen => self.group().map(Primary::Group),
|
|
|
|
Type::Keyword(_) => self.flow().map(Primary::Branch),
|
2023-10-22 23:28:20 +00:00
|
|
|
e => Err(Error::unexpected(e).token(token.clone()))?,
|
2023-10-21 17:24:52 +00:00
|
|
|
}
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
|
|
|
}
|
2023-10-30 04:47:00 +00:00
|
|
|
/// [Call] expressions
|
|
|
|
impl Parser {
|
|
|
|
/// Parses a [call expression](Call)
|
|
|
|
fn call(&mut self) -> PResult<Call> {
|
|
|
|
let callee = self.primary()?;
|
2024-01-04 08:18:09 +00:00
|
|
|
if self.matches(Type::LParen).is_err() {
|
2023-10-30 04:47:00 +00:00
|
|
|
return Ok(Call::Primary(callee));
|
|
|
|
};
|
|
|
|
let mut args = vec![];
|
|
|
|
while self.consume_type(Type::LParen).is_ok() {
|
|
|
|
match self.consume_type(Type::RParen) {
|
|
|
|
Ok(_) => args.push(Tuple { elements: vec![] }),
|
|
|
|
Err(_) => {
|
|
|
|
args.push(self.tuple()?);
|
|
|
|
self.consume_type(Type::RParen)?;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Ok(Call::FnCall(FnCall { callee: callee.into(), args }))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Groups and Tuples
|
|
|
|
impl Parser {
|
|
|
|
/// Parses a [group expression](Group)
|
|
|
|
fn group(&mut self) -> PResult<Group> {
|
|
|
|
let t = self.consume_type(Type::LParen)?.peek()?;
|
|
|
|
match t.ty() {
|
|
|
|
Type::RParen => {
|
|
|
|
self.consume();
|
|
|
|
Ok(Group::Empty)
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
let mut out = self.tuple()?;
|
|
|
|
let out = if out.elements.len() == 1 {
|
|
|
|
Group::Single(out.elements.remove(0).into())
|
|
|
|
} else {
|
|
|
|
Group::Tuple(out)
|
|
|
|
};
|
|
|
|
self.consume_type(Type::RParen)?;
|
|
|
|
Ok(out)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/// Parses a [tuple expression](Tuple)
|
|
|
|
fn tuple(&mut self) -> PResult<Tuple> {
|
|
|
|
let mut elements = vec![self.expr()?];
|
|
|
|
while self.consume_type(Type::Comma).is_ok() {
|
|
|
|
elements.push(self.expr()?);
|
|
|
|
}
|
|
|
|
Ok(Tuple { elements })
|
|
|
|
}
|
|
|
|
}
|
2023-10-17 18:36:21 +00:00
|
|
|
|
|
|
|
/// Helper macro for math parsing subexpressions with production
|
|
|
|
/// ```ebnf
|
|
|
|
/// Ret = a (b a)*
|
|
|
|
/// ```
|
|
|
|
/// # Examples
|
|
|
|
/// ```rust,ignore
|
2023-10-19 19:40:03 +00:00
|
|
|
/// binary!{
|
2023-10-17 18:36:21 +00:00
|
|
|
/// function_name: ret::Value = parse_operands, parse_operators;
|
|
|
|
/// }
|
|
|
|
/// ```
|
|
|
|
/// becomes
|
|
|
|
/// ```rust,ignore
|
2024-01-04 08:18:09 +00:00
|
|
|
/// fn function_name(&mut self) -> PResult<ret::Value> { ... }
|
2023-10-17 18:36:21 +00:00
|
|
|
/// ```
|
2023-10-21 17:24:52 +00:00
|
|
|
macro binary ($($f:ident = $a:ident, $b:ident);*$(;)?) {$(
|
2024-01-04 08:18:09 +00:00
|
|
|
#[doc = concat!("Parses a(n) [", stringify!($f), " operation](Operation::Binary) expression")]
|
|
|
|
fn $f (&mut self) -> PResult<Operation> {
|
2023-10-29 06:13:48 +00:00
|
|
|
let (first, mut other) = (self.$a()?, vec![]);
|
2023-10-21 17:24:52 +00:00
|
|
|
while let Ok(op) = self.$b() {
|
2023-10-29 06:13:48 +00:00
|
|
|
other.push((op, self.$a()?));
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
2023-10-29 06:13:48 +00:00
|
|
|
Ok(if other.is_empty() { first } else {
|
|
|
|
Operation::Binary(Binary { first: first.into(), other })
|
2023-10-21 17:24:52 +00:00
|
|
|
})
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
|
|
|
)*}
|
|
|
|
/// # [Arithmetic and Logical Subexpressions](math)
|
2023-10-22 23:28:20 +00:00
|
|
|
impl Parser {
|
2024-01-04 08:18:09 +00:00
|
|
|
fn assign(&mut self) -> PResult<Operation> {
|
2023-10-29 06:13:48 +00:00
|
|
|
let next = self.compare()?;
|
|
|
|
let Ok(operator) = self.assign_op() else {
|
|
|
|
return Ok(next);
|
|
|
|
};
|
2023-10-30 04:47:00 +00:00
|
|
|
let Operation::Call(Call::Primary(Primary::Identifier(target))) = next else {
|
2023-10-29 06:13:48 +00:00
|
|
|
return Ok(next);
|
|
|
|
};
|
|
|
|
Ok(Operation::Assign(Assign {
|
|
|
|
target,
|
|
|
|
operator,
|
|
|
|
init: self.assign()?.into(),
|
|
|
|
}))
|
|
|
|
}
|
2023-10-19 19:40:03 +00:00
|
|
|
binary! {
|
2023-10-26 19:36:55 +00:00
|
|
|
// name operands operators
|
2023-10-22 23:30:00 +00:00
|
|
|
compare = range, compare_op;
|
|
|
|
range = logic, range_op;
|
2023-10-21 17:24:52 +00:00
|
|
|
logic = bitwise, logic_op;
|
|
|
|
bitwise = shift, bitwise_op;
|
|
|
|
shift = term, shift_op;
|
|
|
|
term = factor, term_op;
|
|
|
|
factor = unary, factor_op;
|
|
|
|
}
|
2024-01-04 08:18:09 +00:00
|
|
|
/// Parses a [unary operation](Operation::Unary) expression
|
|
|
|
fn unary(&mut self) -> PResult<Operation> {
|
2023-10-21 17:24:52 +00:00
|
|
|
let mut operators = vec![];
|
|
|
|
while let Ok(op) = self.unary_op() {
|
|
|
|
operators.push(op)
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
2023-10-29 06:13:48 +00:00
|
|
|
if operators.is_empty() {
|
|
|
|
return self.primary_operation();
|
|
|
|
}
|
|
|
|
Ok(Operation::Unary(Unary {
|
|
|
|
operators,
|
|
|
|
operand: self.primary_operation()?.into(),
|
|
|
|
}))
|
|
|
|
}
|
2024-01-04 08:18:09 +00:00
|
|
|
/// Parses a [primary operation](Operation::Primary) expression
|
|
|
|
fn primary_operation(&mut self) -> PResult<Operation> {
|
|
|
|
Ok(Operation::Call(self.call()?))
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
|
|
|
}
|
2023-10-21 17:24:52 +00:00
|
|
|
macro operator_impl ($($(#[$m:meta])* $f:ident : {$($type:pat => $op:ident),*$(,)?})*) {
|
|
|
|
$($(#[$m])* fn $f(&mut self) -> PResult<operator::Binary> {
|
|
|
|
use operator::Binary;
|
2024-01-04 08:18:09 +00:00
|
|
|
let token = self.peek().wrap(Error::not_operator())?;
|
2023-10-21 17:24:52 +00:00
|
|
|
let out = Ok(match token.ty() {
|
|
|
|
$($type => Binary::$op,)*
|
2023-10-22 23:28:20 +00:00
|
|
|
_ => Err(Error::not_operator().token(token.clone()))?,
|
2023-10-21 17:24:52 +00:00
|
|
|
});
|
|
|
|
self.consume();
|
2023-10-17 18:36:21 +00:00
|
|
|
out
|
2023-10-21 17:24:52 +00:00
|
|
|
})*
|
|
|
|
}
|
2023-10-17 18:36:21 +00:00
|
|
|
/// # [Operators](operator)
|
2023-10-22 23:28:20 +00:00
|
|
|
impl Parser {
|
2023-10-17 18:36:21 +00:00
|
|
|
operator_impl! {
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Parses a [factor operator](operator)
|
2023-10-21 17:24:52 +00:00
|
|
|
factor_op: {
|
|
|
|
Type::Star => Mul,
|
|
|
|
Type::Slash => Div,
|
|
|
|
Type::Rem => Rem,
|
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Parses a [term operator](operator)
|
2023-10-21 17:24:52 +00:00
|
|
|
term_op: {
|
|
|
|
Type::Plus => Add,
|
|
|
|
Type::Minus => Sub,
|
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Parses a [shift operator](operator)
|
2023-10-21 17:24:52 +00:00
|
|
|
shift_op: {
|
|
|
|
Type::LtLt => Lsh,
|
|
|
|
Type::GtGt => Rsh,
|
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Parses a [bitwise operator](operator)
|
2023-10-21 17:24:52 +00:00
|
|
|
bitwise_op: {
|
|
|
|
Type::Amp => BitAnd,
|
|
|
|
Type::Bar => BitOr,
|
|
|
|
Type::Xor => BitXor,
|
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Parses a [logic operator](operator)
|
2023-10-21 17:24:52 +00:00
|
|
|
logic_op: {
|
|
|
|
Type::AmpAmp => LogAnd,
|
|
|
|
Type::BarBar => LogOr,
|
|
|
|
Type::XorXor => LogXor,
|
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Parses a [range operator](operator)
|
2023-10-22 23:30:00 +00:00
|
|
|
range_op: {
|
|
|
|
Type::DotDot => RangeExc,
|
|
|
|
Type::DotDotEq => RangeInc,
|
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Parses a [compare operator](operator)
|
2023-10-21 17:24:52 +00:00
|
|
|
compare_op: {
|
|
|
|
Type::Lt => Less,
|
|
|
|
Type::LtEq => LessEq,
|
|
|
|
Type::EqEq => Equal,
|
|
|
|
Type::BangEq => NotEq,
|
|
|
|
Type::GtEq => GreaterEq,
|
|
|
|
Type::Gt => Greater,
|
|
|
|
}
|
2023-10-29 06:13:48 +00:00
|
|
|
}
|
|
|
|
/// Parses an [assign operator](operator::Assign)
|
|
|
|
fn assign_op(&mut self) -> PResult<operator::Assign> {
|
|
|
|
use operator::Assign;
|
|
|
|
let token = self.peek()?;
|
|
|
|
let out = Ok(match token.ty() {
|
|
|
|
Type::Eq => Assign::Assign,
|
|
|
|
Type::PlusEq => Assign::AddAssign,
|
|
|
|
Type::MinusEq => Assign::SubAssign,
|
|
|
|
Type::StarEq => Assign::MulAssign,
|
|
|
|
Type::SlashEq => Assign::DivAssign,
|
|
|
|
Type::RemEq => Assign::RemAssign,
|
|
|
|
Type::AmpEq => Assign::BitAndAssign,
|
|
|
|
Type::BarEq => Assign::BitOrAssign,
|
|
|
|
Type::XorEq => Assign::BitXorAssign,
|
|
|
|
Type::LtLtEq => Assign::ShlAssign,
|
|
|
|
Type::GtGtEq => Assign::ShrAssign,
|
|
|
|
_ => Err(Error::not_operator().token(token.clone()))?,
|
|
|
|
});
|
|
|
|
self.consume();
|
|
|
|
out
|
2023-10-21 17:24:52 +00:00
|
|
|
}
|
2023-10-26 19:41:59 +00:00
|
|
|
/// Parses a [unary operator](operator::Unary)
|
2023-10-21 17:24:52 +00:00
|
|
|
fn unary_op(&mut self) -> PResult<operator::Unary> {
|
|
|
|
use operator::Unary;
|
2023-10-22 23:28:20 +00:00
|
|
|
let token = self.peek()?;
|
2023-10-21 17:24:52 +00:00
|
|
|
let out = Ok(match token.ty() {
|
|
|
|
Type::AmpAmp => Unary::RefRef,
|
|
|
|
Type::Amp => Unary::Ref,
|
|
|
|
Type::Star => Unary::Deref,
|
|
|
|
Type::Minus => Unary::Neg,
|
|
|
|
Type::Bang => Unary::Not,
|
|
|
|
Type::At => Unary::At,
|
|
|
|
Type::Hash => Unary::Hash,
|
|
|
|
Type::Tilde => Unary::Tilde,
|
2023-10-22 23:28:20 +00:00
|
|
|
_ => Err(Error::not_operator().token(token.clone()))?,
|
2023-10-21 17:24:52 +00:00
|
|
|
});
|
|
|
|
self.consume();
|
|
|
|
out
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
/// # [Control Flow](control)
|
2023-10-22 23:28:20 +00:00
|
|
|
impl Parser {
|
2024-01-04 08:18:09 +00:00
|
|
|
/// Parses a [control flow](Flow) expression
|
|
|
|
fn flow(&mut self) -> PResult<Flow> {
|
2023-10-19 19:40:03 +00:00
|
|
|
use Keyword::{Break, Continue, For, If, Return, While};
|
2023-10-22 23:28:20 +00:00
|
|
|
let token = self.peek()?;
|
2023-10-17 18:36:21 +00:00
|
|
|
match token.ty() {
|
2023-10-19 19:40:03 +00:00
|
|
|
Type::Keyword(While) => self.parse_while().map(Flow::While),
|
|
|
|
Type::Keyword(For) => self.parse_for().map(Flow::For),
|
|
|
|
Type::Keyword(If) => self.parse_if().map(Flow::If),
|
|
|
|
Type::Keyword(Break) => self.parse_break().map(Flow::Break),
|
|
|
|
Type::Keyword(Return) => self.parse_return().map(Flow::Return),
|
|
|
|
Type::Keyword(Continue) => self.parse_continue().map(Flow::Continue),
|
2023-10-22 23:28:20 +00:00
|
|
|
e => Err(Error::unexpected(e).token(token.clone()))?,
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
2024-01-04 08:18:09 +00:00
|
|
|
.wrap(Error::not_branch())
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
2024-01-04 08:18:09 +00:00
|
|
|
/// Parses an [if](If) expression
|
|
|
|
fn parse_if(&mut self) -> PResult<If> {
|
2023-10-19 19:40:03 +00:00
|
|
|
self.keyword(Keyword::If)?;
|
2024-01-04 08:18:09 +00:00
|
|
|
Ok(If { cond: self.expr()?.into(), body: self.block()?, else_: self.parse_else()? })
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
2024-01-04 08:18:09 +00:00
|
|
|
/// Parses a [while](While) expression
|
|
|
|
fn parse_while(&mut self) -> PResult<While> {
|
2023-10-19 19:40:03 +00:00
|
|
|
self.keyword(Keyword::While)?;
|
2024-01-04 08:18:09 +00:00
|
|
|
Ok(While { cond: self.expr()?.into(), body: self.block()?, else_: self.parse_else()? })
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
2024-01-04 08:18:09 +00:00
|
|
|
/// Parses a [for](For) expression
|
|
|
|
fn parse_for(&mut self) -> PResult<For> {
|
2023-10-17 18:36:21 +00:00
|
|
|
self.keyword(Keyword::For)?;
|
2024-01-04 08:18:09 +00:00
|
|
|
Ok(For {
|
2023-10-17 18:36:21 +00:00
|
|
|
var: self.identifier()?,
|
|
|
|
iter: { self.keyword(Keyword::In)?.expr()?.into() },
|
|
|
|
body: self.block()?,
|
|
|
|
else_: self.parse_else()?,
|
|
|
|
})
|
|
|
|
}
|
2024-01-04 08:18:09 +00:00
|
|
|
/// Parses an [else](Else) sub-expression
|
|
|
|
fn parse_else(&mut self) -> PResult<Option<Else>> {
|
2023-10-17 18:36:21 +00:00
|
|
|
// it's fine for `else` to be missing entirely
|
2023-10-19 19:40:03 +00:00
|
|
|
self.keyword(Keyword::Else)
|
|
|
|
.ok()
|
2024-01-04 08:18:09 +00:00
|
|
|
.map(|p| Ok(Else { expr: p.expr()?.into() }))
|
2023-10-19 19:40:03 +00:00
|
|
|
.transpose()
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
2024-01-04 08:18:09 +00:00
|
|
|
/// Parses a [break](Break) expression
|
|
|
|
fn parse_break(&mut self) -> PResult<Break> {
|
|
|
|
Ok(Break { expr: self.keyword(Keyword::Break)?.expr()?.into() })
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
2024-01-04 08:18:09 +00:00
|
|
|
/// Parses a [return](Return) expression
|
|
|
|
fn parse_return(&mut self) -> PResult<Return> {
|
|
|
|
Ok(Return { expr: self.keyword(Keyword::Return)?.expr()?.into() })
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
2024-01-04 08:18:09 +00:00
|
|
|
/// Parses a [continue](Continue) expression
|
|
|
|
fn parse_continue(&mut self) -> PResult<Continue> {
|
2023-10-21 17:24:52 +00:00
|
|
|
self.keyword(Keyword::Continue)?;
|
2024-01-04 08:18:09 +00:00
|
|
|
Ok(Continue)
|
2023-10-17 18:36:21 +00:00
|
|
|
}
|
|
|
|
}
|