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