Start writing parser
This commit is contained in:
parent
38a90cf1fa
commit
9a4c342586
|
@ -3,10 +3,13 @@
|
||||||
use std::{error::Error, fmt::Display};
|
use std::{error::Error, fmt::Display};
|
||||||
|
|
||||||
use chumsky::{
|
use chumsky::{
|
||||||
prelude::{filter, Simple},
|
prelude::{choice, empty, end, just, todo, Simple},
|
||||||
|
text::{ident, keyword},
|
||||||
Parser,
|
Parser,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use crate::syntax::{ClassMember, Expr, Pattern, Statement, SyntaxTree, Type, TypeConstructor};
|
||||||
|
|
||||||
/// Adapter to make `chumsky`'s parser errors usable as standard Rust errors.
|
/// Adapter to make `chumsky`'s parser errors usable as standard Rust errors.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct ParserError(pub Vec<Simple<char>>);
|
pub struct ParserError(pub Vec<Simple<char>>);
|
||||||
|
@ -23,14 +26,108 @@ impl Display for ParserError {
|
||||||
impl Error for ParserError {}
|
impl Error for ParserError {}
|
||||||
|
|
||||||
/// Parser for AlexScript code.
|
/// Parser for AlexScript code.
|
||||||
pub fn parser() -> impl Parser<char, crate::syntax::SyntaxTree, Error = Simple<char>> {
|
pub fn parser() -> impl Parser<char, SyntaxTree, Error = Simple<char>> {
|
||||||
filter(|c: &char| c.is_numeric()).map(|_| todo!())
|
parse_statement()
|
||||||
|
.repeated()
|
||||||
|
.map(SyntaxTree)
|
||||||
|
.then_ignore(end())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_expression() -> impl Parser<char, crate::syntax::Expr, Error = Simple<char>> {
|
fn parse_statement() -> impl Parser<char, Statement, Error = Simple<char>> {
|
||||||
parser().map(|_| todo!())
|
choice((
|
||||||
|
parse_type_def(),
|
||||||
|
parse_instance_def(),
|
||||||
|
parse_class_def(),
|
||||||
|
parse_class_decl_stmt(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_type() -> impl Parser<char, crate::syntax::Type, Error = Simple<char>> {
|
fn parse_type_def() -> impl Parser<char, Statement, Error = Simple<char>> {
|
||||||
parser().map(|_| todo!())
|
keyword("data")
|
||||||
|
.ignore_then(parse_type())
|
||||||
|
.then_ignore(just('='))
|
||||||
|
.then(parse_constructor().repeated())
|
||||||
|
.then_ignore(just(';'))
|
||||||
|
.map(|(typ, constructors)| Statement::TypeDefinition { typ, constructors })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_constructor() -> impl Parser<char, TypeConstructor, Error = Simple<char>> {
|
||||||
|
ident()
|
||||||
|
.then(parse_type().repeated())
|
||||||
|
.map(|(name, args)| TypeConstructor { name, args })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_instance_def() -> impl Parser<char, Statement, Error = Simple<char>> {
|
||||||
|
keyword("instance")
|
||||||
|
.ignore_then(ident())
|
||||||
|
.then(parse_type())
|
||||||
|
.then(
|
||||||
|
parse_class_member()
|
||||||
|
.repeated()
|
||||||
|
.delimited_by(just('{'), just('}')),
|
||||||
|
)
|
||||||
|
.map(|((classname, typ), decls)| Statement::InstanceDefinition {
|
||||||
|
class_name: classname,
|
||||||
|
typ,
|
||||||
|
decls,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_class_decl_stmt() -> impl Parser<char, Statement, Error = Simple<char>> {
|
||||||
|
parse_class_member().map(Statement::ClassMember)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_class_member() -> impl Parser<char, ClassMember, Error = Simple<char>> {
|
||||||
|
choice((parse_func_decl(), parse_type_alias()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_func_decl() -> impl Parser<char, ClassMember, Error = Simple<char>> {
|
||||||
|
keyword("def")
|
||||||
|
.ignore_then(ident())
|
||||||
|
.then(parse_pattern().repeated())
|
||||||
|
.then(choice((
|
||||||
|
just('=').ignore_then(parse_expression()).map(Some),
|
||||||
|
empty().to(None),
|
||||||
|
)))
|
||||||
|
.then_ignore(just(';'))
|
||||||
|
.map(|((name, arguments), definition)| ClassMember::Function {
|
||||||
|
name,
|
||||||
|
arguments,
|
||||||
|
definition,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_type_alias() -> impl Parser<char, ClassMember, Error = Simple<char>> {
|
||||||
|
keyword("type")
|
||||||
|
.ignore_then(parse_type())
|
||||||
|
.then(choice((
|
||||||
|
just('=').ignore_then(parse_type()).map(Some),
|
||||||
|
empty().to(None),
|
||||||
|
)))
|
||||||
|
.then_ignore(just(';'))
|
||||||
|
.map(|(left, right)| ClassMember::TypeAlias { left, right })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_class_def() -> impl Parser<char, Statement, Error = Simple<char>> {
|
||||||
|
keyword("class")
|
||||||
|
.ignore_then(ident())
|
||||||
|
.then(ident())
|
||||||
|
.then(
|
||||||
|
parse_class_member()
|
||||||
|
.repeated()
|
||||||
|
.delimited_by(just('{'), just('}')),
|
||||||
|
)
|
||||||
|
.map(|((name, var), decls)| Statement::ClassDefinition { name, var, decls })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_expression() -> impl Parser<char, Expr, Error = Simple<char>> {
|
||||||
|
todo()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_type() -> impl Parser<char, Type, Error = Simple<char>> {
|
||||||
|
todo()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_pattern() -> impl Parser<char, Pattern, Error = Simple<char>> {
|
||||||
|
todo()
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,14 +5,16 @@ use num_bigint::BigUint;
|
||||||
/// A concrete syntax tree. This represents the full content of an AlexScript program, including all
|
/// A concrete syntax tree. This represents the full content of an AlexScript program, including all
|
||||||
/// whitespace, comments, and tokens: the source code of the original program can be recovered
|
/// whitespace, comments, and tokens: the source code of the original program can be recovered
|
||||||
/// completely using the syntax tree.
|
/// completely using the syntax tree.
|
||||||
pub struct SyntaxTree {}
|
#[derive(Clone)]
|
||||||
|
pub struct SyntaxTree(pub Vec<Statement>);
|
||||||
|
|
||||||
/// Top-level statements, making up the overall program.
|
/// Top-level statements, making up the overall program.
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum Statement {
|
pub enum Statement {
|
||||||
/// Declaration of an abstract data type.
|
/// Declaration of an abstract data type.
|
||||||
TypeDefinition {
|
TypeDefinition {
|
||||||
/// The type being defined. This is only allowed to be `Named` or `Application`.
|
/// The type being defined. This is only allowed to be `Named` or `Application`.
|
||||||
left: Type,
|
typ: Type,
|
||||||
|
|
||||||
/// The possible constructors of the data type.
|
/// The possible constructors of the data type.
|
||||||
constructors: Vec<TypeConstructor>,
|
constructors: Vec<TypeConstructor>,
|
||||||
|
@ -28,20 +30,34 @@ pub enum Statement {
|
||||||
|
|
||||||
/// The list of declarations that dictate the type's behavior when treated as an instance of
|
/// The list of declarations that dictate the type's behavior when treated as an instance of
|
||||||
/// the type class.
|
/// the type class.
|
||||||
decls: Vec<ClassDeclaration>,
|
decls: Vec<ClassMember>,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Declaration of a type class.
|
||||||
|
ClassDefinition {
|
||||||
|
/// The name of the class.
|
||||||
|
name: String,
|
||||||
|
|
||||||
|
/// The type variable representing a type conforming to the class.
|
||||||
|
var: String,
|
||||||
|
|
||||||
|
/// The list of declarations (optionally filled-in) that are necessary for a type to conform
|
||||||
|
/// to the type class.
|
||||||
|
decls: Vec<ClassMember>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Other declarations.
|
/// Other declarations.
|
||||||
ClassDeclaration(ClassDeclaration),
|
ClassMember(ClassMember),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Top-level statements that are also allowed to occur within a type class definition, and which
|
/// Top-level statements that are also allowed to occur within a type class definition, and which
|
||||||
/// therefore have an optional rather than strictly-required right-hand side, e.g., `type X;` rather
|
/// therefore have an optional rather than strictly-required right-hand side, e.g., `type X;` rather
|
||||||
/// than `type X = Y;`.
|
/// than `type X = Y;`.
|
||||||
pub enum ClassDeclaration {
|
#[derive(Clone)]
|
||||||
|
pub enum ClassMember {
|
||||||
/// Declaration of a function or constant.
|
/// Declaration of a function or constant.
|
||||||
Function {
|
Function {
|
||||||
/// Name of the function and its arguments.
|
/// Name of the function.
|
||||||
name: String,
|
name: String,
|
||||||
|
|
||||||
/// The function arguments.
|
/// The function arguments.
|
||||||
|
@ -59,22 +75,10 @@ pub enum ClassDeclaration {
|
||||||
/// The target type.
|
/// The target type.
|
||||||
right: Option<Type>,
|
right: Option<Type>,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Declaration of a type class.
|
|
||||||
ClassDefinition {
|
|
||||||
/// The name of the class.
|
|
||||||
name: String,
|
|
||||||
|
|
||||||
/// The type variable representing a type conforming to the class.
|
|
||||||
var: String,
|
|
||||||
|
|
||||||
/// The list of declarations (optionally filled-in) that are necessary for a type to conform
|
|
||||||
/// to the type class.
|
|
||||||
decls: Vec<ClassDeclaration>,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A possible constructor for an abstract data type.
|
/// A possible constructor for an abstract data type.
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct TypeConstructor {
|
pub struct TypeConstructor {
|
||||||
/// The name of the constructor.
|
/// The name of the constructor.
|
||||||
pub name: String,
|
pub name: String,
|
||||||
|
@ -84,6 +88,7 @@ pub struct TypeConstructor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expressions.
|
/// Expressions.
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum Expr {
|
pub enum Expr {
|
||||||
/// Unary operators, e.g., `-5`.
|
/// Unary operators, e.g., `-5`.
|
||||||
UnaryOp {
|
UnaryOp {
|
||||||
|
@ -179,6 +184,7 @@ pub enum Expr {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Type names.
|
/// Type names.
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum Type {
|
pub enum Type {
|
||||||
/// `Foo`
|
/// `Foo`
|
||||||
Named(String),
|
Named(String),
|
||||||
|
@ -202,6 +208,7 @@ pub enum Type {
|
||||||
|
|
||||||
/// Patterns for use in function arguments, lambda arguments, `let` statements, and `match`
|
/// Patterns for use in function arguments, lambda arguments, `let` statements, and `match`
|
||||||
/// statements.
|
/// statements.
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum Pattern {
|
pub enum Pattern {
|
||||||
/// `(a, b)`
|
/// `(a, b)`
|
||||||
Tuple(Vec<Pattern>),
|
Tuple(Vec<Pattern>),
|
||||||
|
@ -232,6 +239,7 @@ pub enum Pattern {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Record syntax blocks, e.g., "{a: b, c: d, ...}".
|
/// Record syntax blocks, e.g., "{a: b, c: d, ...}".
|
||||||
|
#[derive(Clone)]
|
||||||
pub struct Record {
|
pub struct Record {
|
||||||
/// The named members of the record, in order of occurrence.
|
/// The named members of the record, in order of occurrence.
|
||||||
pub members: Vec<(String, Expr)>,
|
pub members: Vec<(String, Expr)>,
|
||||||
|
@ -241,6 +249,7 @@ pub struct Record {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Literal values included in source code.
|
/// Literal values included in source code.
|
||||||
|
#[derive(Clone)]
|
||||||
pub enum Literal {
|
pub enum Literal {
|
||||||
/// `"hello"`
|
/// `"hello"`
|
||||||
String(String),
|
String(String),
|
||||||
|
|
Loading…
Reference in a new issue