Start writing parser

This commit is contained in:
Alex Bethel 2022-08-05 17:55:31 -05:00
parent 38a90cf1fa
commit 9a4c342586
2 changed files with 132 additions and 26 deletions

View file

@ -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()
} }

View file

@ -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),