Update the lexer to match changes to the grammar
This commit is contained in:
parent
756bb883f0
commit
250d40dab7
|
@ -25,8 +25,8 @@
|
|||
<rank5_expr> ::= <rank6_expr> { <rank5_op> <rank6_expr> }
|
||||
<rank6_expr> ::= <rank7_expr> { <rank6_op> <rank7_expr> }
|
||||
<rank7_expr> ::= <tightexpr> { <rank7_op> <tightexpr> }
|
||||
<rank1_op> ::= LOr
|
||||
<rank2_op> ::= LAnd
|
||||
<rank1_op> ::= LOr | VBar
|
||||
<rank2_op> ::= LAnd | Aro
|
||||
<rank3_op> ::= Eq | NEq | LessThan | GreaterThan
|
||||
<rank5_op> ::= Range
|
||||
<rank6_op> ::= Add | Sub
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
type MyType
|
||||
= Variant1
|
||||
| Variant2 int[usize]
|
||||
| Variant3 str int[0..21]
|
||||
MyType: Type
|
||||
MyType = type
|
||||
Variant1
|
||||
| Variant2 (int 0..usize)
|
||||
| Variant3 str (int 0..21)
|
||||
|
||||
myFunc: str, int -> MyType
|
||||
myFunc strval intval =
|
||||
|
@ -9,8 +10,9 @@ myFunc strval intval =
|
|||
then Variant3 strval intval
|
||||
else Variant1
|
||||
|
||||
type ComplexType
|
||||
= ComplexVariant (str, int -> MyType) str
|
||||
ComplexType: Type
|
||||
ComplexType = type
|
||||
ComplexVariant (str, int -> MyType) str
|
||||
|
||||
myVal : ComplexType
|
||||
myVal = ComplexVariant myFunc "uwu~"
|
||||
|
|
|
@ -2,73 +2,36 @@ use std::mem::{Discriminant, discriminant};
|
|||
|
||||
use crate::token::Token;
|
||||
|
||||
use super::{Parsable, WrappedLexer, ParseError, absorb_token_or_error, types::{TightType, FullType}, expr::Expr};
|
||||
use super::{Parsable, WrappedLexer, ParseError, absorb_token_or_error, expr::Expr};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Declaration {
|
||||
Type {
|
||||
pub struct Declaration {
|
||||
name: String,
|
||||
first_variants: Variant,
|
||||
other_variants: Vec<Variant>,
|
||||
},
|
||||
/*Struct {
|
||||
name: String,
|
||||
typeargs: Vec<TypeArg>,
|
||||
first_fields: Field,
|
||||
other_fields: Vec<Field>,
|
||||
},
|
||||
Trait {
|
||||
name: String,
|
||||
typeargs: Vec<TypeArg>,
|
||||
on: Option<CompositeType>,
|
||||
},
|
||||
Impl(ImplDecl),*/
|
||||
Symbol {
|
||||
name: String,
|
||||
type_: FullType,
|
||||
type_: Expr,
|
||||
name2: String,
|
||||
args: Vec<String>,
|
||||
value: Expr,
|
||||
},
|
||||
Empty,
|
||||
}
|
||||
|
||||
impl Parsable for Declaration {
|
||||
fn expected() -> (Vec<Discriminant<Token>>, bool) {
|
||||
(vec![
|
||||
discriminant(&Token::Symbol("".to_string())),
|
||||
discriminant(&Token::Type),
|
||||
], false)
|
||||
}
|
||||
fn parse(l: &mut WrappedLexer) -> Result<Self, ParseError> {
|
||||
let span = l.span();
|
||||
match l.monch() {
|
||||
// Type Symbol Assign <variant_decl> { VBar <variant_decl> }
|
||||
Token::Type => {
|
||||
let name = String::parse(l)?;
|
||||
absorb_token_or_error(l, discriminant(&Token::Assign))?;
|
||||
let first_variants = Variant::parse(l)?;
|
||||
let mut other_variants = Vec::new();
|
||||
while *l.curtok() == Token::VBar {
|
||||
l.monch();
|
||||
other_variants.push(Variant::parse(l)?);
|
||||
}
|
||||
Ok(Self::Type {
|
||||
first_variants,
|
||||
other_variants,
|
||||
name,
|
||||
})
|
||||
},
|
||||
// Symbol Colon <full_type> DeclarationStart Symbol { Symbol } Assign <expr>
|
||||
Token::Symbol(name) => {
|
||||
absorb_token_or_error(l, discriminant(&Token::Colon))?;
|
||||
let type_ = FullType::parse(l)?;
|
||||
let type_ = Expr::parse(l)?;
|
||||
absorb_token_or_error(l, discriminant(&Token::DeclarationStart))?;
|
||||
let name2 = String::parse(l)?;
|
||||
let args = Vec::parse(l)?;
|
||||
absorb_token_or_error(l, discriminant(&Token::Assign))?;
|
||||
let value = Expr::parse(l)?;
|
||||
Ok(Self::Symbol {
|
||||
Ok(Self {
|
||||
name,
|
||||
name2,
|
||||
args,
|
||||
|
@ -76,9 +39,6 @@ impl Parsable for Declaration {
|
|||
value,
|
||||
})
|
||||
},
|
||||
Token::EOF | Token::DeclarationStart => {
|
||||
Ok(Self::Empty)
|
||||
},
|
||||
_ => {
|
||||
Err(ParseError {
|
||||
expected: Self::expected().0,
|
||||
|
@ -88,25 +48,3 @@ impl Parsable for Declaration {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Variant {
|
||||
name: String,
|
||||
elements: Vec<TightType>,
|
||||
}
|
||||
|
||||
impl Parsable for Variant {
|
||||
fn expected() -> (Vec<Discriminant<Token>>, bool) {
|
||||
(
|
||||
vec![discriminant(&Token::Symbol(String::new()))],
|
||||
false,
|
||||
)
|
||||
}
|
||||
fn parse(l: &mut WrappedLexer) -> Result<Self, ParseError> {
|
||||
// <variant_declaration> ::= Symbol { <grouped_type> }
|
||||
Ok(Variant {
|
||||
name: String::parse(l)?,
|
||||
elements: Vec::parse(l)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
// <expr> ::= <tiGHtexpr> { <tightexpr> }
|
||||
// | If <expr> <ifblock>
|
||||
// <expr> ::= If <expr> <ifblock>
|
||||
// | <let> { <let> } In <expr>
|
||||
// | <infix_expr>
|
||||
// | TypeOp <expr>
|
||||
//
|
||||
// <tightexpr> ::= Literal
|
||||
// | OpenParen <expr> CloseParen
|
||||
|
@ -24,6 +24,7 @@ pub enum Expr {
|
|||
If(Box<Expr>, Box<IfBlock>),
|
||||
Let(Box<LetStmt>, Vec<LetStmt>, Box<Expr>),
|
||||
Infix(Rank1Exp),
|
||||
Type(Box<Expr>),
|
||||
}
|
||||
|
||||
impl Parsable for Expr {
|
||||
|
@ -32,6 +33,7 @@ impl Parsable for Expr {
|
|||
expected.extend_from_slice(&[
|
||||
discriminant(&Token::Let),
|
||||
discriminant(&Token::If),
|
||||
discriminant(&Token::TypeOp),
|
||||
]);
|
||||
(expected, false)
|
||||
}
|
||||
|
@ -49,6 +51,11 @@ impl Parsable for Expr {
|
|||
let in_expr = Expr::parse(l)?;
|
||||
Ok(Expr::Let(Box::new(initial_let), subsequent_lets, Box::new(in_expr)))
|
||||
}
|
||||
Token::TypeOp => {
|
||||
l.monch();
|
||||
let value = Expr::parse(l)?;
|
||||
Ok(Expr::Type(Box::new(value)))
|
||||
}
|
||||
Token::If => {
|
||||
l.monch();
|
||||
let cond = Expr::parse(l)?;
|
||||
|
@ -172,7 +179,7 @@ impl Parsable for Case {
|
|||
|
||||
fn parse(l: &mut WrappedLexer) -> Result<Self, ParseError> {
|
||||
let pattern = BindingPattern::parse(l)?;
|
||||
absorb_token_or_error(l, discriminant(&Token::Aro))?;
|
||||
absorb_token_or_error(l, discriminant(&Token::DubAro))?;
|
||||
let expr = Expr::parse(l)?;
|
||||
Ok(Case(pattern, expr))
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ use std::mem::discriminant;
|
|||
|
||||
pub mod program;
|
||||
pub mod declaration;
|
||||
pub mod types;
|
||||
pub mod expr;
|
||||
pub mod pattern;
|
||||
pub mod infix;
|
||||
|
|
|
@ -1,85 +0,0 @@
|
|||
// <full_type> ::= <tight_type> [ Comma [ <additional_type> ] [ Aro <full_type> ] ]
|
||||
// <additional_type> ::= <tight_type> [ Comma [ <additional_type> ] ]
|
||||
// <tight_type> ::= OpenParen <full_type> CloseParen
|
||||
// | Symbol [ OpenSquareBracket <domain> CloseSquareBracket ]
|
||||
// <domain> ::= <expr> [ Comma [ <domain> ] ]
|
||||
|
||||
use std::mem::{Discriminant, discriminant};
|
||||
|
||||
use crate::token::Token;
|
||||
|
||||
use super::{Parsable, WrappedLexer, parse_delineated_vec, absorb_token_or_error, ParseError, expr::Expr};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum TightType {
|
||||
Grouped(Box<FullType>),
|
||||
Simple {
|
||||
name: String,
|
||||
domains: Vec<Expr>,
|
||||
},
|
||||
}
|
||||
|
||||
impl Parsable for TightType {
|
||||
fn expected() -> (Vec<Discriminant<Token>>, bool) {
|
||||
(
|
||||
vec![
|
||||
discriminant(&Token::OpenParen),
|
||||
discriminant(&Token::Symbol(String::new())),
|
||||
],
|
||||
false,
|
||||
)
|
||||
}
|
||||
fn parse(l: &mut WrappedLexer) -> Result<Self, ParseError> {
|
||||
let span = l.span();
|
||||
match l.monch() {
|
||||
Token::Symbol(name) => {
|
||||
let domains: Vec<Expr> = if *l.curtok() == Token::OpenSquareBracket {
|
||||
l.monch();
|
||||
let d = parse_delineated_vec(l, discriminant(&Token::Comma))?;
|
||||
absorb_token_or_error(l, discriminant(&Token::CloseSquareBracket))?;
|
||||
d
|
||||
} else {
|
||||
Vec::new()
|
||||
};
|
||||
Ok(TightType::Simple { name, domains })
|
||||
}
|
||||
Token::OpenParen => {
|
||||
let full_type = Box::new(FullType::parse(l)?);
|
||||
absorb_token_or_error(l, discriminant(&Token::CloseParen))?;
|
||||
Ok(TightType::Grouped(full_type))
|
||||
}
|
||||
_ => Err(ParseError {
|
||||
location: span,
|
||||
expected: Self::expected().0,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum FullType {
|
||||
Simple(TightType),
|
||||
Function(Vec<TightType>, Box<FullType>),
|
||||
}
|
||||
|
||||
impl Parsable for FullType {
|
||||
fn expected() -> (Vec<Discriminant<Token>>, bool) {
|
||||
TightType::expected()
|
||||
}
|
||||
// <full_type> ::= <tight_type> [ Comma [ <additional_type> ] [ Aro <full_type> ] ]
|
||||
fn parse(l: &mut WrappedLexer) -> Result<Self, ParseError> {
|
||||
let first_type = TightType::parse(l)?;
|
||||
if let Token::Comma = l.curtok() {
|
||||
l.monch();
|
||||
let other_args = parse_delineated_vec(l, discriminant(&Token::Comma))?;
|
||||
absorb_token_or_error(l, discriminant(&Token::Aro))?;
|
||||
let result = Box::new(FullType::parse(l)?);
|
||||
let mut args = Vec::with_capacity(1 + other_args.len());
|
||||
args.push(first_type);
|
||||
args.extend(other_args);
|
||||
Ok(FullType::Function(args, result))
|
||||
} else {
|
||||
Ok(FullType::Simple(first_type))
|
||||
}
|
||||
}
|
||||
}
|
29
src/token.rs
29
src/token.rs
|
@ -103,11 +103,11 @@ pub enum Token {
|
|||
#[token("in")]
|
||||
In, //d12
|
||||
|
||||
/// An `->` arrow
|
||||
/// An `=>` arrow
|
||||
///
|
||||
/// Used as part of function type annotations as well as in the cases of If-Is blocks
|
||||
#[token("->")]
|
||||
Aro, //d13
|
||||
#[token("=>")]
|
||||
DubAro, //d13
|
||||
|
||||
/// An `=` assignment operator
|
||||
///
|
||||
|
@ -115,11 +115,9 @@ pub enum Token {
|
|||
#[token("=")]
|
||||
Assign, //d14
|
||||
|
||||
/// The `|` keyword (or punctuation? idk what it's called)
|
||||
///
|
||||
/// Used in deliniating variants of a type
|
||||
#[token("|")]
|
||||
VBar, //d15
|
||||
/// Type Operator
|
||||
#[token("type", priority = 9)]
|
||||
TypeOp, //d15
|
||||
|
||||
/// The `_` symbol
|
||||
///
|
||||
|
@ -137,12 +135,15 @@ pub enum Token {
|
|||
///
|
||||
/// i.e. Logical Or
|
||||
#[token("||", |_| InfixRank1::LOr)]
|
||||
#[token("|", |_| InfixRank1::VBar)]
|
||||
R1Infix(InfixRank1), //d18
|
||||
|
||||
/// A rank 2 infix binop (binary operator)
|
||||
///
|
||||
/// i.e. Logical And
|
||||
#[token("&&", |_| InfixRank2::LAnd)]
|
||||
#[token("->", |_| InfixRank2::Aro)]
|
||||
#[token(",", |_| InfixRank2::Aro)]
|
||||
R2Infix(InfixRank2), //d19
|
||||
|
||||
/// A rank 3 infix binop (binary operator)
|
||||
|
@ -225,7 +226,7 @@ pub enum Token {
|
|||
/// A `,` comma
|
||||
///
|
||||
/// The age-old and timeless delineator
|
||||
#[token(",")]
|
||||
#[token(";")]
|
||||
Comma, //d31
|
||||
|
||||
/// A newline NOT followed by whitespace
|
||||
|
@ -245,7 +246,7 @@ pub enum Token {
|
|||
///
|
||||
/// simply lexes to `Symbol(variable)`, `Assign`, `Symbol(value)`. This makes it easy
|
||||
/// to identify declarations.
|
||||
#[regex(r"\s*\n")]
|
||||
#[regex(r"(\s*\n)+")]
|
||||
DeclarationStart, //d32
|
||||
|
||||
/// Denotes that the parser has reached the end of the input
|
||||
|
@ -261,6 +262,11 @@ pub enum InfixRank1 {
|
|||
///
|
||||
/// Takes two boolean values and returns true if either is true
|
||||
LOr,
|
||||
|
||||
/// The VBar operator
|
||||
///
|
||||
/// Takes two variant sets and returns sum
|
||||
VBar,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
|
@ -270,6 +276,9 @@ pub enum InfixRank2 {
|
|||
/// Takes two boolean values and returns true iff both values are true. Otherwise,
|
||||
/// returns false.
|
||||
LAnd,
|
||||
|
||||
/// The Aro operator
|
||||
Aro,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||
|
|
Loading…
Reference in a new issue