Some parsing test cases.

This commit is contained in:
2025-09-06 20:41:36 -07:00
parent 129bf3c204
commit 1baeae1bf0

View File

@@ -48,10 +48,12 @@ impl Location {
} }
} }
#[derive(Debug)]
pub struct Module { pub struct Module {
definitions: Vec<Definition>, definitions: Vec<Definition>,
} }
#[derive(Debug)]
pub struct Definition { pub struct Definition {
location: Location, location: Location,
export: ExportClass, export: ExportClass,
@@ -59,6 +61,7 @@ pub struct Definition {
definition: Def, definition: Def,
} }
#[derive(Debug)]
pub enum Def { pub enum Def {
Enumeration(EnumerationDef), Enumeration(EnumerationDef),
Structure(StructureDef), Structure(StructureDef),
@@ -77,28 +80,33 @@ impl Def {
} }
} }
#[derive(Debug)]
pub struct EnumerationDef { pub struct EnumerationDef {
location: Location, location: Location,
options: Vec<EnumerationVariant>, options: Vec<EnumerationVariant>,
} }
#[derive(Debug)]
pub struct EnumerationVariant { pub struct EnumerationVariant {
location: Location, location: Location,
name: String, name: String,
arguments: Vec<Type>, arguments: Vec<Type>,
} }
#[derive(Debug)]
pub struct StructureDef { pub struct StructureDef {
name: String, name: String,
location: Location, location: Location,
fields: Vec<StructureField>, fields: Vec<StructureField>,
} }
#[derive(Debug)]
pub struct StructureField { pub struct StructureField {
name: String, name: String,
field_type: Type, field_type: Type,
} }
#[derive(Debug)]
pub struct FunctionDef { pub struct FunctionDef {
name: String, name: String,
location: Location, location: Location,
@@ -107,26 +115,31 @@ pub struct FunctionDef {
body: Vec<Statement>, body: Vec<Statement>,
} }
#[derive(Debug)]
pub struct FunctionArg { pub struct FunctionArg {
name: String, name: String,
arg_type: Option<Type>, arg_type: Option<Type>,
} }
#[derive(Debug)]
pub struct ValueDef { pub struct ValueDef {
name: String, name: String,
location: Location, location: Location,
value: Value, value: Value,
} }
#[derive(Debug)]
pub enum ExportClass { pub enum ExportClass {
Public, Public,
Private, Private,
} }
#[derive(Debug)]
pub enum Statement { pub enum Statement {
Binding(BindingStmt), Binding(BindingStmt),
} }
#[derive(Debug)]
pub struct BindingStmt { pub struct BindingStmt {
location: Location, location: Location,
mutable: bool, mutable: bool,
@@ -134,10 +147,12 @@ pub struct BindingStmt {
value: Expression, value: Expression,
} }
#[derive(Debug)]
pub enum Expression { pub enum Expression {
Value(Value), Value(Value),
} }
#[derive(Debug)]
pub struct TypeRestrictions { pub struct TypeRestrictions {
restrictions: Vec<TypeRestriction>, restrictions: Vec<TypeRestriction>,
} }
@@ -150,24 +165,28 @@ impl TypeRestrictions {
} }
} }
#[derive(Debug)]
pub struct TypeRestriction { pub struct TypeRestriction {
location: Location, location: Location,
class: String, class: String,
variables: Vec<String>, variables: Vec<String>,
} }
#[derive(Debug)]
pub enum Type { pub enum Type {
Constructor(Location, String), Constructor(Location, String),
Variable(Location, String), Variable(Location, String),
Primitive(Location, String), Primitive(Location, String),
Application(Box<Type>, Vec<Type>), Application(Box<Type>, Vec<Type>),
Function(Vec<Type>, Box<Type>), Function(Box<Type>, Box<Type>),
} }
#[derive(Debug)]
pub enum Value { pub enum Value {
Constant(ConstantValue), Constant(ConstantValue),
} }
#[derive(Debug)]
pub enum ConstantValue { pub enum ConstantValue {
Integer(Location, IntegerWithBase), Integer(Location, IntegerWithBase),
Character(Location, char), Character(Location, char),
@@ -249,3 +268,58 @@ fn can_parse_constants() {
Ok(ConstantValue::Character(_, 'f')) Ok(ConstantValue::Character(_, 'f'))
)); ));
} }
#[test]
fn can_parse_types() {
let parse_type = |str| {
let lexer = Lexer::from(str).map(|item| {
item.map_err(|e| ParserError::LexerError {
file_id: 0,
error: e,
})
});
let result = TypeParser::new().parse(0, lexer);
result
};
println!("cons result: {:?}", parse_type("Cons"));
assert!(matches!(
parse_type("Cons"),
Ok(Type::Application(cons, empty)) if
matches!(cons.as_ref(), Type::Constructor(_, c) if c == "Cons") &&
empty.is_empty()
));
assert!(matches!(
parse_type("cons"),
Ok(Type::Variable(_, c)) if c == "cons"
));
assert!(matches!(
parse_type("Cons a b"),
Ok(Type::Application(a, b))
if matches!(a.as_ref(), Type::Constructor(_, c) if c == "Cons") &&
matches!(b.as_slice(), [Type::Variable(_, b1), Type::Variable(_, b2)]
if b1 == "a" && b2 == "b")
));
assert!(matches!(
parse_type("a -> z"),
Ok(Type::Function(a, z))
if matches!(a.as_slice(), [Type::Variable(_, a1)] if a1 == "a") &&
matches!(z.as_ref(), Type::Variable(_, z1) if z1 == "z")
));
assert!(matches!(
parse_type("a b -> z"),
Ok(Type::Function(a, z))
if matches!(a.as_slice(), [Type::Variable(_, a1), Type::Variable(_, b1)]
if a1 == "a" && b1 == "b") &&
matches!(z.as_ref(), Type::Variable(_, z1) if z1 == "z")
));
assert!(matches!(
parse_type("Cons a b -> z"),
Ok(Type::Function(a, z))
if matches!(a.as_slice(), [Type::Application(cons, appargs)]
if matches!(cons.as_ref(), Type::Constructor(_, c) if c == "Cons") &&
matches!(appargs.as_slice(), [Type::Variable(_, b1), Type::Variable(_, b2)]
if b1 == "a" && b2 == "b")) &&
matches!(z.as_ref(), Type::Variable(_, z1) if z1 == "z")
));
}