Some parsing test cases.
This commit is contained in:
@@ -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")
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user