cl-parser: break parser into inline module

This commit is contained in:
John 2024-02-29 20:43:40 -06:00
parent cc281fc6ab
commit ab17ebbadc

View File

@ -5,17 +5,11 @@
//! [1]: https://git.soft.fish/j/Conlang/src/branch/main/grammar.ebnf
#![feature(decl_macro)]
pub use parser::Parser;
use cl_structures::span::*;
use cl_token::*;
use crate::error::{
Error,
ErrorKind::{self, *},
PResult, Parsing,
};
use cl_ast::*;
use conlang::lexer::Lexer;
pub mod error {
use super::*;
@ -228,19 +222,28 @@ pub mod error {
}
}
pub mod parser {
use super::*;
use crate::error::{
Error,
ErrorKind::{self, *},
PResult, Parsing,
};
use cl_ast::*;
use conlang::lexer::Lexer;
/// Parses a sequence of [Tokens](Token) into an [AST](cl_ast)
pub struct Parser<'t> {
/// Parses a sequence of [Tokens](Token) into an [AST](cl_ast)
pub struct Parser<'t> {
/// Lazy tokenizer
lexer: Lexer<'t>,
/// Look-ahead buffer
next: Option<Token>,
/// The location of the current token
loc: Loc,
}
}
/// Basic parser functionality
impl<'t> Parser<'t> {
/// Basic parser functionality
impl<'t> Parser<'t> {
pub fn new(lexer: Lexer<'t>) -> Self {
Self { loc: Loc::from(&lexer), lexer, next: None }
}
@ -310,39 +313,39 @@ impl<'t> Parser<'t> {
pub fn match_kw(&mut self, pat: Keyword, while_parsing: Parsing) -> PResult<Token> {
self.match_type(Type::Keyword(pat), while_parsing)
}
}
}
// the three matched delimiter pairs
/// Square brackets: `[` `]`
const BRACKETS: (Type, Type) = (Type::LBrack, Type::RBrack);
/// Curly braces: `{` `}`
const CURLIES: (Type, Type) = (Type::LCurly, Type::RCurly);
/// Parentheses: `(` `)`
const PARENS: (Type, Type) = (Type::LParen, Type::RParen);
// the three matched delimiter pairs
/// Square brackets: `[` `]`
const BRACKETS: (Type, Type) = (Type::LBrack, Type::RBrack);
/// Curly braces: `{` `}`
const CURLIES: (Type, Type) = (Type::LCurly, Type::RCurly);
/// Parentheses: `(` `)`
const PARENS: (Type, Type) = (Type::LParen, Type::RParen);
/// Parses constructions of the form `delim.0 f delim.1` (i.e. `(` `foobar` `)`)
const fn delim<'t, T>(
/// Parses constructions of the form `delim.0 f delim.1` (i.e. `(` `foobar` `)`)
const fn delim<'t, T>(
f: impl Fn(&mut Parser<'t>) -> PResult<T>,
delim: (Type, Type),
while_parsing: Parsing,
) -> impl Fn(&mut Parser<'t>) -> PResult<T> {
) -> impl Fn(&mut Parser<'t>) -> PResult<T> {
move |parser| {
parser.match_type(delim.0, while_parsing)?;
let out = f(parser)?;
parser.match_type(delim.1, while_parsing)?;
Ok(out)
}
}
}
/// Parses constructions of the form `(f sep ~until)*`
///
/// where `~until` is a negative lookahead assertion
const fn sep<'t, T>(
/// Parses constructions of the form `(f sep ~until)*`
///
/// where `~until` is a negative lookahead assertion
const fn sep<'t, T>(
f: impl Fn(&mut Parser<'t>) -> PResult<T>,
sep: Type,
until: Type,
while_parsing: Parsing,
) -> impl Fn(&mut Parser<'t>) -> PResult<Vec<T>> {
) -> impl Fn(&mut Parser<'t>) -> PResult<Vec<T>> {
move |parser| {
let mut args = vec![];
while until != parser.peek_type(while_parsing)? {
@ -354,17 +357,17 @@ const fn sep<'t, T>(
}
Ok(args)
}
}
}
/// Parses constructions of the form `(f ~until)*`
///
/// where `~until` is a negative lookahead assertion
#[allow(dead_code)]
const fn rep<'t, T>(
/// Parses constructions of the form `(f ~until)*`
///
/// where `~until` is a negative lookahead assertion
#[allow(dead_code)]
const fn rep<'t, T>(
f: impl Fn(&mut Parser<'t>) -> PResult<T>,
until: Type,
while_parsing: Parsing,
) -> impl Fn(&mut Parser<'t>) -> PResult<Vec<T>> {
) -> impl Fn(&mut Parser<'t>) -> PResult<Vec<T>> {
move |parser| {
let mut out = vec![];
while until != parser.peek_type(while_parsing)? {
@ -372,10 +375,10 @@ const fn rep<'t, T>(
}
Ok(out)
}
}
}
/// Expands to a pattern which matches item-like [Token] [Type]s
macro item_like() {
/// Expands to a pattern which matches item-like [Token] [Type]s
macro item_like() {
Type::Hash
| Type::Keyword(
Keyword::Pub
@ -388,10 +391,10 @@ macro item_like() {
| Keyword::Enum
| Keyword::Impl,
)
}
}
/// Top level parsing
impl<'t> Parser<'t> {
/// Top level parsing
impl<'t> Parser<'t> {
/// Parses a [File]
pub fn file(&mut self) -> PResult<File> {
let mut items = vec![];
@ -469,10 +472,10 @@ impl<'t> Parser<'t> {
pub fn expr(&mut self) -> PResult<Expr> {
self.expr_from(Self::exprkind)
}
}
}
/// Attribute parsing
impl<'t> Parser<'t> {
/// Attribute parsing
impl<'t> Parser<'t> {
/// Parses an [attribute set](Attrs)
pub fn attributes(&mut self) -> PResult<Attrs> {
if self.match_type(Type::Hash, Parsing::Attrs).is_err() {
@ -504,10 +507,10 @@ impl<'t> Parser<'t> {
_ => MetaKind::Plain,
})
}
}
}
/// Item parsing
impl<'t> Parser<'t> {
/// Item parsing
impl<'t> Parser<'t> {
/// Parses an [ItemKind]
///
/// See also: [Parser::item]
@ -704,10 +707,10 @@ impl<'t> Parser<'t> {
};
Ok(Mutability::Not)
}
}
}
/// # Type parsing
impl<'t> Parser<'t> {
/// # Type parsing
impl<'t> Parser<'t> {
/// Parses a [TyKind]
///
/// See also: [Parser::ty]
@ -773,22 +776,22 @@ impl<'t> Parser<'t> {
},
})
}
}
}
/// Expands to a pattern which matches literal-like [Type]s
macro literal_like() {
/// Expands to a pattern which matches literal-like [Type]s
macro literal_like() {
Type::Keyword(Keyword::True | Keyword::False)
| Type::String
| Type::Character
| Type::Integer
| Type::Float
}
/// Expands to a pattern which matches path-like [token Types](Type)
macro path_like() {
}
/// Expands to a pattern which matches path-like [token Types](Type)
macro path_like() {
Type::Keyword(Keyword::Super | Keyword::SelfKw) | Type::Identifier | Type::ColonColon
}
/// # Path parsing
impl<'t> Parser<'t> {
}
/// # Path parsing
impl<'t> Parser<'t> {
/// [PathPart] = `super` | `self` | [Identifier]
pub fn path_part(&mut self) -> PResult<PathPart> {
const PARSING: Parsing = Parsing::PathPart;
@ -809,10 +812,10 @@ impl<'t> Parser<'t> {
_ => panic!("Expected token data for {tok:?}"),
}
}
}
}
/// # Statement parsing
impl<'t> Parser<'t> {
/// # Statement parsing
impl<'t> Parser<'t> {
/// Parses a [StmtKind]
///
/// See also: [Parser::stmt]
@ -844,9 +847,9 @@ impl<'t> Parser<'t> {
},
})
}
}
}
macro binary($($name:ident {$lower:ident, $op:ident})*) {
macro binary($($name:ident {$lower:ident, $op:ident})*) {
$(pub fn $name(&mut self) -> PResult<ExprKind> {
let head = self.expr_from(Self::$lower)?;
let mut tail = vec![];
@ -863,8 +866,8 @@ macro binary($($name:ident {$lower:ident, $op:ident})*) {
Ok(Binary { head: head.into(), tail }.into())
})*
}
/// # Expression parsing
impl<'t> Parser<'t> {
/// # Expression parsing
impl<'t> Parser<'t> {
/// Parses an [ExprKind]
///
/// See also: [Parser::expr], [Parser::exprkind_primary]
@ -1085,10 +1088,10 @@ impl<'t> Parser<'t> {
_ => Ok(Group { expr: first.into() }.into()),
}
}
}
}
/// ## Subexpressions
impl<'t> Parser<'t> {
/// ## Subexpressions
impl<'t> Parser<'t> {
/// [Literal] = [String](Type::String) | [Character](Type::Character)
/// | [Float](Type::Float) (TODO) | [Integer](Type::Integer) | `true` | `false`
pub fn literal(&mut self) -> PResult<Literal> {
@ -1127,11 +1130,15 @@ impl<'t> Parser<'t> {
/// [Block] = `{` [Stmt]* `}`
pub fn block(&mut self) -> PResult<Block> {
const PARSING: Parsing = Parsing::Block;
Ok(Block { stmts: delim(rep(Self::stmt, CURLIES.1, PARSING), CURLIES, PARSING)(self)? })
Ok(
Block {
stmts: delim(rep(Self::stmt, CURLIES.1, PARSING), CURLIES, PARSING)(self)?,
},
)
}
}
/// ## Control flow subexpressions
impl<'t> Parser<'t> {
}
/// ## Control flow subexpressions
impl<'t> Parser<'t> {
/// [Break] = `break` [Expr]?
pub fn parse_break(&mut self) -> PResult<Break> {
self.match_kw(Keyword::Break, Parsing::Break)?;
@ -1189,9 +1196,9 @@ impl<'t> Parser<'t> {
Err(e) => Err(e),
}
}
}
}
macro operator($($name:ident ($returns:ident) {$($t:ident => $p:ident),*$(,)?};)*) {$(
macro operator($($name:ident ($returns:ident) {$($t:ident => $p:ident),*$(,)?};)*) {$(
pub fn $name (&mut self) -> PResult<$returns> {
const PARSING: Parsing = Parsing::$returns;
let out = Ok(match self.peek_type(PARSING) {
@ -1204,8 +1211,8 @@ macro operator($($name:ident ($returns:ident) {$($t:ident => $p:ident),*$(,)?};)
}
)*}
/// ## Operator Kinds
impl<'t> Parser<'t> {
/// ## Operator Kinds
impl<'t> Parser<'t> {
operator! {
assign_op (AssignKind) {
Eq => Plain, // =
@ -1272,4 +1279,5 @@ impl<'t> Parser<'t> {
self.consume_peeked();
Ok(())
}
}
}