Skip to content

Commit

Permalink
Finish parser
Browse files Browse the repository at this point in the history
  • Loading branch information
AlSchlo committed Feb 9, 2025
1 parent 1caa03e commit b899699
Show file tree
Hide file tree
Showing 5 changed files with 633 additions and 403 deletions.
153 changes: 97 additions & 56 deletions optd-core/src/dsl/parser/ast.rs
Original file line number Diff line number Diff line change
@@ -1,112 +1,153 @@
use std::collections::HashMap;

/// Types supported by the language
#[derive(Debug, Clone, PartialEq)]
pub enum Type {
Int64,
String,
Bool,
Float64,
Array(Box<Type>),
Map(Box<Type>, Box<Type>),
Tuple(Vec<Type>),
Function(Box<Type>, Box<Type>), // Function type: (input) -> output
Array(Box<Type>), // Array types like [T]
Map(Box<Type>, Box<Type>), // Map types like map[K->V]
Tuple(Vec<Type>), // Tuple types like (T1, T2)
Function(Box<Type>, Box<Type>), // Function types like (T1)->T2
Operator(OperatorKind), // Operator types (scalar/logical)
}

/// Kinds of operators supported in the language
#[derive(Debug, Clone, PartialEq)]
pub enum OperatorKind {
Scalar, // Scalar operators
Logical, // Logical operators with derivable properties
}

/// A field in an operator or properties block
#[derive(Debug, Clone)]
pub struct Field {
pub name: String,
pub ty: Type,
}

/// Logical properties block that must appear exactly once per file
#[derive(Debug, Clone)]
pub struct Properties {
pub fields: Vec<Field>,
}

/// Top-level operator definition
#[derive(Debug, Clone)]
pub enum Operator {
Scalar(ScalarOp),
Logical(LogicalOp),
}

/// Scalar operator definition
#[derive(Debug, Clone)]
pub struct ScalarOp {
pub name: String,
pub fields: Vec<Field>,
}

/// Logical operator definition with derived properties
#[derive(Debug, Clone)]
pub struct LogicalOp {
pub name: String,
pub fields: Vec<Field>,
pub derived_props: HashMap<String, Expr>,
pub derived_props: HashMap<String, Expr>, // Maps property names to their derivation expressions
}

/// Patterns used in match expressions
#[derive(Debug, Clone)]
pub enum Pattern {
Bind(String, Box<Pattern>),
Constructor(String, Vec<(String, Pattern)>),
Enum(String, Option<Box<Pattern>>),
Literal(Literal),
Wildcard,
Var(String),
Bind(String, Box<Pattern>), // Binding patterns like x@p or x:p
Constructor(
String, // Constructor name
Vec<Pattern>, // Subpatterns, can be named (x:p) or positional
),
Literal(Literal), // Literal patterns like 42 or "hello"
Wildcard, // Wildcard pattern _
Var(String), // Variable binding pattern
}

/// Literal values
#[derive(Debug, Clone)]
pub enum Literal {
Number(i64),
StringLit(String),
Boolean(bool),
Int64(i64),
String(String),
Bool(bool),
Float64(f64),
Array(Vec<Expr>), // Array literals [e1, e2, ...]
Tuple(Vec<Expr>), // Tuple literals (e1, e2, ...)
}

/// Expressions - the core of the language
#[derive(Debug, Clone)]
pub enum Expr {
Match(Box<Expr>, Vec<(Pattern, Block)>),
If(Box<Expr>, Box<Block>, Option<Box<Block>>),
Val(String, Box<Expr>, Box<Expr>),
Array(Vec<Expr>),
Map(Vec<(Expr, Expr)>),
Range(Box<Expr>, Box<Expr>),
Binary(Box<Expr>, BinOp, Box<Expr>),
Call(Box<Expr>, Vec<Expr>),
Member(Box<Expr>, String),
MemberCall(Box<Expr>, String, Vec<Expr>),
Var(String),
Literal(Literal),
Constructor(String, Vec<(String, Expr)>),
Fail(String),
Closure(Vec<String>, Box<Expr>),
Match(Box<Expr>, Vec<MatchArm>), // Pattern matching
If(Box<Expr>, Box<Expr>, Box<Expr>), // If-then-else
Val(String, Box<Expr>, Box<Expr>), // Local binding (val x = e1; e2)
Array(Vec<Expr>), // Array literals
Tuple(Vec<Expr>), // Tuple literals
Constructor(String, Vec<Expr>), // Constructor application (currently only operators)
Binary(Box<Expr>, BinOp, Box<Expr>), // Binary operations
Unary(UnaryOp, Box<Expr>), // Unary operations
Call(Box<Expr>, Vec<Expr>), // Function application
Member(Box<Expr>, String), // Field access (e.f)
MemberCall(Box<Expr>, String, Vec<Expr>), // Method call (e.f(args))
ArrayIndex(Box<Expr>, Box<Expr>), // Array indexing (e[i])
Var(String), // Variable reference
Literal(Literal), // Literal values
Fail(String), // Failure with message
Closure(Vec<String>, Box<Expr>), // Anonymous functions
}

/// A case in a match expression
#[derive(Debug, Clone)]
pub struct MatchArm {
pub pattern: Pattern,
pub expr: Expr,
}

/// Binary operators with fixed precedence
#[derive(Debug, Clone)]
pub enum BinOp {
Add,
Sub,
Mul,
Div,
Concat,
Eq,
Neq,
Gt,
Lt,
Ge,
Le,
And,
Or,
Add, // +
Sub, // -
Mul, // *
Div, // /
Concat, // ++
Eq, // ==
Neq, // !=
Gt, // >
Lt, // <
Ge, // >=
Le, // <=
And, // &&
Or, // ||
Range, // ..
}

/// Unary operators
#[derive(Debug, Clone)]
pub struct Block {
pub exprs: Vec<Expr>,
pub enum UnaryOp {
Neg, // -
Not, // !
}

/// Function definition
#[derive(Debug, Clone)]
pub struct Function {
pub name: String,
pub params: Vec<(String, Type)>,
pub params: Vec<(String, Type)>, // Parameter name and type pairs
pub return_type: Type,
pub body: Block,
pub is_rule: bool,
pub is_operator: bool,
pub body: Expr,
pub rule_type: Option<OperatorKind>, // Some if this is a rule, indicating what kind
}

/// A complete source file
#[derive(Debug, Clone)]
pub struct File {
pub operators: Vec<Operator>,
pub functions: Vec<Function>,
pub properties: Properties, // The single logical properties block
pub operators: Vec<Operator>, // All operator definitions
pub functions: Vec<Function>, // All function definitions
}

#[derive(Debug, Clone)]
pub enum Operator {
Scalar(ScalarOp),
Logical(LogicalOp),
}
83 changes: 62 additions & 21 deletions optd-core/src/dsl/parser/grammar.pest
Original file line number Diff line number Diff line change
@@ -1,25 +1,56 @@
KEYWORD = {
"Bool" |
"Float64" |
"Int64" |
"Logical" |
"Map" |
"Props" |
"Scalar" |
"String" |
"case" |
"def" |
"derive" |
"else" |
"fail" |
"false" |
"if" |
"match" |
"then" |
"true" |
"val"
}

// Whitespace and comments
WHITESPACE = _{ " " | "\t" | "\r" | "\n" }
COMMENT = _{ "//" ~ (!"\n" ~ ANY)* }

// Basic identifiers and literals
identifier = @{ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC | "_")* }
identifier = @{
!KEYWORD ~ ASCII_ALPHA ~ (ASCII_ALPHANUMERIC | "_")*
}
number = @{ "-"? ~ ASCII_DIGIT+ }
string = @{ "\"" ~ (!"\"" ~ ANY)* ~ "\"" }
boolean = { "true" | "false" }

// Types
operator_type = { "scalar" | "logical" }
base_type = { "i64" | "String" | "Bool" | "f64" }
operator_type = { "Scalar" | "Logical" }
base_type = { "Int64" | "String" | "Bool" | "Float64" }
array_type = { "[" ~ type_expr ~ "]" }
map_type = { "map" ~ "[" ~ type_expr ~ "->" ~ type_expr ~ "]" }
tuple_type = { "[" ~ type_expr ~ ("," ~ type_expr)* ~ "]" }
map_type = { "Map" ~ "[" ~ type_expr ~ "," ~ type_expr ~ "]" }
tuple_type = { "(" ~ type_expr ~ "," ~ type_expr ~ ("," ~ type_expr)* ~ ")" }
function_type = { "(" ~ type_expr ~ ")" ~ "->" ~ type_expr } // Function composition type
type_expr = { operator_type | base_type | array_type | map_type | tuple_type | function_type }
type_expr = {
function_type
| operator_type
| base_type
| array_type
| map_type
| tuple_type
}

// Annotations
props_annot = { "logical" ~ "props" }
rule_annot = { "@rule" ~ "(" ~ ("scalar" | "logical") ~ ")" }
props_annot = { "Logical" ~ "Props" }
rule_annot = { "@rule" ~ "(" ~ ("Scalar" | "Logical") ~ ")" }

// Operators
operator_def = {
Expand Down Expand Up @@ -55,12 +86,12 @@ prop_derivation = { identifier ~ "=" ~ expr }

// Functions
function_def = { normal_function | rule_def }
normal_function = {
normal_function = _{
"def" ~ identifier ~ "(" ~ params? ~ ")" ~ ":" ~ type_expr ~ "=" ~ NEWLINE?
~ (expr | "{" ~ NEWLINE? ~ expr ~ NEWLINE? ~ "}") // Braces optional
}

rule_def = {
rule_def = _{
rule_annot ~ NEWLINE?
~ normal_function
}
Expand All @@ -74,7 +105,7 @@ pattern = {
| top_level_pattern
}

top_level_pattern = {
top_level_pattern = _{
constructor_pattern
| literal_pattern
| wildcard_pattern
Expand Down Expand Up @@ -111,21 +142,30 @@ expr = {
| (closure | logical_or)
}

// Operators as separate rules
or_op = { "||" }
and_op = { "&&" }
compare_op = { "==" | "!=" | ">=" | "<=" | ">" | "<" }
concat_op = { "++" }
add_op = { "+" | "-" }
range_op = { ".." }
mult_op = { "*" | "/" }

// Closure is lowest precedence
closure = { closure_params ~ "=>" ~ expr }
closure_params = {
"(" ~ (identifier ~ ("," ~ identifier)*)? ~ ")"
| identifier // Single param case
}

logical_or = { logical_and ~ ("||" ~ logical_and)* }
logical_and = { comparison ~ ("&&" ~ comparison)* }
comparison = { concatenation ~ (("==" | "!=" | ">=" | "<=" | ">" | "<") ~ concatenation)* }
concatenation = { additive ~ ("++" ~ additive)* }
additive = { range ~ (("+" | "-") ~ range)* }
range = { multiplicative ~ (".." ~ multiplicative)* }
multiplicative = { postfix ~ (("*" | "/") ~ postfix)* }
postfix = { prefix ~ (call | member_access | array_index | member_call)* }
logical_or = { logical_and ~ (or_op ~ logical_and)* }
logical_and = { comparison ~ (and_op ~ comparison)* }
comparison = { concatenation ~ (compare_op ~ concatenation)* }
concatenation = { additive ~ (concat_op ~ additive)* }
additive = { range ~ (add_op ~ range)* }
range = { multiplicative ~ (range_op ~ multiplicative)* }
multiplicative = { postfix ~ (mult_op ~ postfix)* }
postfix = { prefix ~ (member_call | member_access | call | array_index)* }
prefix = { ("!" | "-")? ~ primary }

primary = _{
Expand All @@ -152,7 +192,7 @@ constructor_expr = {
identifier ~ "(" ~ constructor_fields? ~ ")"
}

constructor_fields = {
constructor_fields = _{
expr ~ ("," ~ expr)*
}

Expand Down Expand Up @@ -193,6 +233,7 @@ val_expr = { "val" ~ identifier ~ "=" ~ expr ~ ";" ~ expr }
// Full file
file = {
SOI ~
(operator_def | props_block | function_def)* ~
props_block ~
(operator_def | function_def)* ~
EOI
}
Loading

0 comments on commit b899699

Please sign in to comment.