cl-parser: break parser into inline module
This commit is contained in:
parent
cc281fc6ab
commit
ab17ebbadc
@ -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(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user