update parser
This commit is contained in:
parent
546af734e7
commit
6a27f8fdf8
144
src/albireo.pest
144
src/albireo.pest
@ -17,54 +17,133 @@ keywords = {
|
|||||||
| "import"
|
| "import"
|
||||||
| "module"
|
| "module"
|
||||||
| "export"
|
| "export"
|
||||||
|
| "record"
|
||||||
|
| "tuple"
|
||||||
|
| "type"
|
||||||
|
| "enum"
|
||||||
|
| "auto"
|
||||||
}
|
}
|
||||||
identifier = @{ !keywords ~ ASCII_ALPHA ~ ASCII_ALPHANUMERIC* }
|
|
||||||
|
|
||||||
function_type_param = { type }
|
// if identifier starts with something like a keyword, it must follows something else
|
||||||
function_type_return = { type }
|
// in any case, the identifier cannot begin with a digit
|
||||||
|
identifier = @{ keywords? ~ ("_" | ASCII_ALPHANUMERIC)+
|
||||||
|
| !keywords ~ ASCII_ALPHA ~ ("_" | ASCII_ALPHANUMERIC)* }
|
||||||
|
|
||||||
|
function_type_param = { type* }
|
||||||
|
function_type_return = _{ type }
|
||||||
function_type = {
|
function_type = {
|
||||||
"fn" ~ function_type_param* ~ "=>" ~ function_type_return
|
"fn" ~ function_type_param ~ "=>" ~ function_type_return
|
||||||
}
|
}
|
||||||
|
|
||||||
type = {
|
// record name { prop: type, prop: type, prop: type }
|
||||||
|
record_type_field = { identifier ~ ":" ~ type }
|
||||||
|
record_type_fields = _{ record_type_field ~ "," ~ record_type_fields | record_type_field }
|
||||||
|
record_type = {
|
||||||
|
"record" ~ "{" ~ record_type_fields ~ "}"
|
||||||
|
}
|
||||||
|
|
||||||
|
// tuple (type, type)
|
||||||
|
tuple_type_item = _{ type }
|
||||||
|
tuple_type_item_list = _{ tuple_type_item ~ "," ~ tuple_type_item_list | tuple_type_item }
|
||||||
|
tuple_type = {
|
||||||
|
"tuple" ~ "(" ~ tuple_type_item_list ~ ")"
|
||||||
|
}
|
||||||
|
|
||||||
|
// enum name { name: type, name: type }
|
||||||
|
enum_field = { identifier ~ ":" ~ type }
|
||||||
|
enum_fields = _{ enum_field ~ "," ~ enum_fields | enum_field }
|
||||||
|
enum_type = {
|
||||||
|
"enum" ~ "{" ~ enum_fields ~ "}"
|
||||||
|
}
|
||||||
|
|
||||||
|
// allow for type alias, aka create new type
|
||||||
|
type_name = { identifier }
|
||||||
|
type_declaration = { "type" ~ type_name ~ "=" ~ type }
|
||||||
|
|
||||||
|
type_number = { "number" }
|
||||||
|
type_string = { "string" }
|
||||||
|
type_bool = { "bool" }
|
||||||
|
|
||||||
|
// for gradual typing
|
||||||
|
type_auto = { "?" | "auto" }
|
||||||
|
|
||||||
|
// higher-kinded types will be added later
|
||||||
|
// this will be very complex to parse,
|
||||||
|
// because allowing types to receive an argument as type
|
||||||
|
type = _{
|
||||||
function_type
|
function_type
|
||||||
| "number"
|
| record_type
|
||||||
| "bool"
|
| tuple_type
|
||||||
| "string"
|
| enum_type
|
||||||
|
| type_name
|
||||||
|
| type_number
|
||||||
|
| type_bool
|
||||||
|
| type_string
|
||||||
}
|
}
|
||||||
|
|
||||||
number = @{ ASCII_DIGIT+ }
|
number = @{ ASCII_DIGIT+ }
|
||||||
string = @{ "\"" ~ !("\"") ~ ASCII_ALPHANUMERIC* ~ "\"" }
|
string = @{ "\"" ~ !("\"") ~ ASCII_ALPHANUMERIC* ~ "\"" }
|
||||||
bool = @{ "true" | "false" }
|
bool = @{ "true" | "false" }
|
||||||
function = { "function" ~ function_param* ~ "is" ~ function_body }
|
tuple = { "tuple" ~ "(" ~ tuple_item_list ~ ")" }
|
||||||
function_param = { identifier }
|
tuple_item_list = _{ expr ~ "," ~ tuple_item_list | expr }
|
||||||
function_body = {
|
record = { "record" ~ "{" ~ record_item_list ~ "}" }
|
||||||
binding* ~ expr
|
record_item = { identifier ~ ":" ~ expr }
|
||||||
|
record_item_list = _{ record_item ~ "," ~ record_item_list | record_item }
|
||||||
|
function = { "function" ~ function_params ~ "is" ~ function_body }
|
||||||
|
function_params = { function_param* }
|
||||||
|
function_param = _{ identifier }
|
||||||
|
function_body = _{
|
||||||
|
bindings ~ expr
|
||||||
}
|
}
|
||||||
|
bindings = { binding* }
|
||||||
binding = {
|
binding = {
|
||||||
"let" ~ identifier ~ "=" ~ expr ~ "in"
|
"let" ~ identifier ~ "=" ~ expr ~ "in"
|
||||||
}
|
}
|
||||||
|
|
||||||
// will be expr in later version of the language
|
if_cond = _{ expr }
|
||||||
if_cond = { identifier }
|
if_branch = _{ expr }
|
||||||
if_branch = { identifier }
|
else_branch = _{ expr }
|
||||||
else_branch = { identifier }
|
|
||||||
if_expr = {
|
if_expr = {
|
||||||
// "if" ~ expr ~ "then" ~ expr ~ "else" ~ expr
|
|
||||||
"if" ~ if_cond ~ "then" ~ if_branch ~ "else" ~ else_branch
|
"if" ~ if_cond ~ "then" ~ if_branch ~ "else" ~ else_branch
|
||||||
}
|
}
|
||||||
|
|
||||||
call_function = { identifier }
|
call_function = _{ identifier }
|
||||||
call_param = { identifier | identifier ~ call_param }
|
call_param_list = _{ expr ~ ("," ~ expr)* }
|
||||||
|
call_param = { call_param_list? }
|
||||||
call_expr = {
|
call_expr = {
|
||||||
call_function ~ "(" ~ call_param? ~ ")"
|
call_function ~ "(" ~ call_param ~ ")"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binop = _{
|
||||||
|
add
|
||||||
|
| sub
|
||||||
|
| div
|
||||||
|
| mul
|
||||||
|
| mod
|
||||||
|
| and
|
||||||
|
| or
|
||||||
|
| xor
|
||||||
|
}
|
||||||
|
add = { "+" }
|
||||||
|
sub = { "-" }
|
||||||
|
div = { "/" }
|
||||||
|
mul = { "*" }
|
||||||
|
mod = { "%" }
|
||||||
|
and = { "&" }
|
||||||
|
or = { "|" }
|
||||||
|
xor = { "^" }
|
||||||
|
// disambiguous between arithmetic and logical operators
|
||||||
|
// add comparision
|
||||||
|
|
||||||
expr = {
|
expr = {
|
||||||
|
single_expr ~ (binop ~ single_expr)*
|
||||||
|
}
|
||||||
|
single_expr = _{
|
||||||
if_expr
|
if_expr
|
||||||
| call_expr
|
| call_expr
|
||||||
| identifier
|
| identifier
|
||||||
| value
|
| value
|
||||||
|
| "(" ~ expr ~ ")"
|
||||||
}
|
}
|
||||||
|
|
||||||
// function is a value only if we allow to have thunks
|
// function is a value only if we allow to have thunks
|
||||||
@ -74,17 +153,22 @@ value = _{
|
|||||||
number
|
number
|
||||||
| string
|
| string
|
||||||
| bool
|
| bool
|
||||||
|
| tuple
|
||||||
|
| record
|
||||||
| function
|
| function
|
||||||
}
|
}
|
||||||
|
|
||||||
declaration = {
|
variable_declaration = {
|
||||||
identifier ~ ":" ~ type ~ "=" ~ expr
|
identifier ~ ":" ~ type ~ "=" ~ expr
|
||||||
}
|
}
|
||||||
|
declaration = _{
|
||||||
|
type_declaration
|
||||||
|
| variable_declaration
|
||||||
|
}
|
||||||
|
|
||||||
module_name = @{ identifier }
|
module_name = _{ identifier }
|
||||||
export_list = _{
|
export_list = _{
|
||||||
identifier
|
identifier ~ ("," ~ identifier)*
|
||||||
| identifier ~ "," ~ export_list
|
|
||||||
}
|
}
|
||||||
module_export = {
|
module_export = {
|
||||||
"export" ~ export_list
|
"export" ~ export_list
|
||||||
@ -94,24 +178,24 @@ module_export = {
|
|||||||
// import module only name, name
|
// import module only name, name
|
||||||
// import module as change_name
|
// import module as change_name
|
||||||
import_list = _{
|
import_list = _{
|
||||||
identifier ~ "," ~ import_list
|
identifier ~ ("," ~ identifier)*
|
||||||
| identifier
|
|
||||||
}
|
}
|
||||||
import_selective = { "only" ~ import_list }
|
import_selective = { "only" ~ import_list }
|
||||||
import_change_name = { "as" ~ module_name }
|
import_change_name = { "as" ~ module_name }
|
||||||
import_types = {
|
import_types = _{
|
||||||
import_selective
|
import_selective
|
||||||
| import_change_name
|
| import_change_name
|
||||||
}
|
}
|
||||||
module_import = { "import" ~ module_name ~ import_types? }
|
module_import = { "import" ~ module_name ~ import_types? }
|
||||||
|
|
||||||
|
module_export_import = { (module_export | module_import)* }
|
||||||
module_declare = {
|
module_declare = {
|
||||||
"module" ~ module_name ~ module_export* ~ module_import*
|
"module" ~ module_name ~ module_export_import
|
||||||
}
|
}
|
||||||
|
|
||||||
program = {
|
program = {
|
||||||
module_declare ~ declaration*
|
SOI ~ module_declare ~ declaration*
|
||||||
}
|
}
|
||||||
|
|
||||||
WHITESPACE = _{ " " | NEWLINE }
|
WHITESPACE = _{ " " | NEWLINE }
|
||||||
COMMENT = _{ ";.*" ~ NEWLINE }
|
COMMENT = _{ ";" ~ (!NEWLINE ~ ANY)* ~ NEWLINE }
|
||||||
|
361
src/albireo.rs
361
src/albireo.rs
@ -4,30 +4,365 @@ pub struct AlbireoParser;
|
|||||||
|
|
||||||
use pest::iterators::Pair;
|
use pest::iterators::Pair;
|
||||||
|
|
||||||
struct Module {
|
use std::vec::Vec;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, Eq, PartialEq, Hash)]
|
||||||
|
pub struct Identifier {
|
||||||
name: String,
|
name: String,
|
||||||
declaration: HashMap<String, Declaration>
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Declaration {
|
#[derive(Clone, Debug)]
|
||||||
type: Type,
|
pub struct Module {
|
||||||
definition: Expression,
|
module: ModuleInformation,
|
||||||
|
declaration: Vec<Declaration>
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Type {
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct ModuleInformation {
|
||||||
|
name: Identifier,
|
||||||
|
export: Export,
|
||||||
|
import: Vec<Import>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum Export {
|
||||||
|
All,
|
||||||
|
Selective(Vec<Identifier>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Import {
|
||||||
|
from: Identifier,
|
||||||
|
rename: Identifier, // change name, perhaps
|
||||||
|
imported: Vec<Identifier>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum Declaration {
|
||||||
|
Type(Identifier, Type),
|
||||||
|
Variable(Identifier, Type, Box<Expression>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum Type {
|
||||||
|
Identifier(Identifier),
|
||||||
Number,
|
Number,
|
||||||
String,
|
String,
|
||||||
Bool,
|
Bool,
|
||||||
Function(/*inputs*/Vec<Type>, /*output*/Type)
|
Function(/*inputs*/Vec<Type>, /*output*/Box<Type>),
|
||||||
|
Tuple(Vec<Type>),
|
||||||
}
|
}
|
||||||
|
|
||||||
// limitation as of now, everything must be passed in as identifier
|
#[derive(Clone, Debug)]
|
||||||
enum Expression {
|
pub enum BinaryOp {
|
||||||
IfClause(String, String, String),
|
Add, Sub, Div, Mul, Mod, And, Or, Xor
|
||||||
Application(/*function name*/String, /*params*/Vec<String>), // function call
|
}
|
||||||
Identifier(String),
|
|
||||||
|
impl Into<BinaryOp> for &str {
|
||||||
|
fn into(self) -> BinaryOp {
|
||||||
|
match self {
|
||||||
|
"+" => BinaryOp::Add,
|
||||||
|
"-" => BinaryOp::Sub,
|
||||||
|
"*" => BinaryOp::Mul,
|
||||||
|
"/" => BinaryOp::Div,
|
||||||
|
"%" => BinaryOp::Mod,
|
||||||
|
// "<" => BinaryOp::Lt,
|
||||||
|
// ">" => BinaryOp::Gt,
|
||||||
|
// "<=" => BinaryOp::Le,
|
||||||
|
// ">=" => BinaryOp::Ge,
|
||||||
|
// "==" => BinaryOp::Eq,
|
||||||
|
// "!=" => BinaryOp::Neq,
|
||||||
|
// "|" => BinaryOp::ArithOr,
|
||||||
|
// "&" => BinaryOp::ArithAnd,
|
||||||
|
// "||" => BinaryOp::LogicalOr,
|
||||||
|
// "&&" => BinaryOp::LogicalAnd,
|
||||||
|
// "<<" => BinaryOp::ShiftLeft,
|
||||||
|
// ">>" => BinaryOp::ShiftRight,
|
||||||
|
// "**" => BinaryOp::Power,
|
||||||
|
_ => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub enum Expression {
|
||||||
|
IfClause(Box<Expression>, Box<Expression>, Box<Expression>),
|
||||||
|
Application(/*function name*/Identifier, /*params*/Vec<Box<Expression>>), // function call
|
||||||
|
Identifier(Identifier),
|
||||||
Number(u64),
|
Number(u64),
|
||||||
String(String),
|
String(String),
|
||||||
Bool(bool),
|
Bool(bool),
|
||||||
Function(String, Vec<Binding>, Expression),
|
Function(/*params*/Vec<Identifier>, Vec<Binding>, Box<Expression>),
|
||||||
|
Binary(Box<Expression>, BinaryOp, Box<Expression>),
|
||||||
|
Tuple(Vec<Box<Expression>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct Binding {
|
||||||
|
lhs: Identifier,
|
||||||
|
rhs: Box<Expression>,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_definition(parsed: Pair<Rule>) -> Box<Expression> {
|
||||||
|
parse_expr(parsed)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_expr(parsed: Pair<Rule>) -> Box<Expression> {
|
||||||
|
use pest::pratt_parser::PrattParser;
|
||||||
|
use pest::pratt_parser::{Assoc, Op};
|
||||||
|
let pratt =
|
||||||
|
PrattParser::new()
|
||||||
|
.op(Op::infix(Rule::r#mod, Assoc::Left))
|
||||||
|
.op(Op::infix(Rule::add, Assoc::Left) | Op::infix(Rule::sub, Assoc::Left))
|
||||||
|
.op(Op::infix(Rule::mul, Assoc::Left) | Op::infix(Rule::div, Assoc::Left))
|
||||||
|
;
|
||||||
|
|
||||||
|
let expr = pratt
|
||||||
|
.map_primary(|p| {
|
||||||
|
parse_single_expr(p)
|
||||||
|
})
|
||||||
|
.map_infix(|lhs, op, rhs| {
|
||||||
|
Box::new(Expression::Binary(lhs.clone(), op.as_str().into(), rhs.clone()))
|
||||||
|
})
|
||||||
|
.parse(parsed.into_inner());
|
||||||
|
|
||||||
|
expr
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_bindings(parsed: Pair<Rule>) -> Binding {
|
||||||
|
let mut p = parsed.into_inner();
|
||||||
|
Binding {
|
||||||
|
lhs: parse_identifier(p.next().unwrap()),
|
||||||
|
rhs: parse_expr(p.next().unwrap()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_function_expr(parsed: Pair<Rule>) -> Option<Box<Expression>> {
|
||||||
|
let mut p = parsed.into_inner();
|
||||||
|
let parsed_params = p.next()?;
|
||||||
|
let parsed_bindings = p.next()?;
|
||||||
|
let parsed_body = p.next()?;
|
||||||
|
|
||||||
|
let params = parsed_params.into_inner().map(parse_identifier).collect();
|
||||||
|
let bindings = parsed_bindings.into_inner().map(parse_bindings).collect();
|
||||||
|
let body = parse_expr(parsed_body);
|
||||||
|
|
||||||
|
Some(Box::new(Expression::Function(params, bindings, body)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_if_expr(parsed: Pair<Rule>) -> Option<Box<Expression>> {
|
||||||
|
let mut p = parsed.into_inner();
|
||||||
|
let condition = parse_expr(p.next()?);
|
||||||
|
let ifbranch = parse_expr(p.next()?);
|
||||||
|
let elsebranch = parse_expr(p.next()?);
|
||||||
|
Some(Box::new(Expression::IfClause(condition, ifbranch, elsebranch)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_call_expr(parsed: Pair<Rule>) -> Option<Box<Expression>> {
|
||||||
|
let mut p = parsed.into_inner();
|
||||||
|
let identifier = parse_identifier(p.next()?);
|
||||||
|
let parsed_params = p.next()?;
|
||||||
|
let params = parsed_params.into_inner().map(parse_expr).collect();
|
||||||
|
Some(Box::new(Expression::Application(identifier, params)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_single_expr(parsed: Pair<Rule>) -> Box<Expression> {
|
||||||
|
match parsed.as_rule() {
|
||||||
|
Rule::if_expr => {
|
||||||
|
parse_if_expr(parsed).unwrap()
|
||||||
|
},
|
||||||
|
Rule::call_expr => {
|
||||||
|
parse_call_expr(parsed).unwrap()
|
||||||
|
},
|
||||||
|
Rule::identifier => {
|
||||||
|
Box::new(Expression::Identifier(parse_identifier(parsed)))
|
||||||
|
},
|
||||||
|
Rule::number => {
|
||||||
|
let num = parsed.as_str();
|
||||||
|
Box::new(Expression::Number(num.parse().unwrap()))
|
||||||
|
},
|
||||||
|
// Rule::string => {},
|
||||||
|
Rule::bool => {
|
||||||
|
if parsed.as_str() == "false" {
|
||||||
|
Box::new(Expression::Bool(false))
|
||||||
|
} else {
|
||||||
|
Box::new(Expression::Bool(true))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Rule::tuple => {
|
||||||
|
let mut tuple = Vec::new();
|
||||||
|
let mut p = parsed.into_inner();
|
||||||
|
while let Some(e) = p.next() {
|
||||||
|
tuple.push(parse_expr(e));
|
||||||
|
}
|
||||||
|
Box::new(Expression::Tuple(tuple))
|
||||||
|
}
|
||||||
|
Rule::function => {
|
||||||
|
parse_function_expr(parsed).unwrap()
|
||||||
|
}
|
||||||
|
Rule::expr => {
|
||||||
|
let e = parsed.into_inner().next().unwrap();
|
||||||
|
parse_expr(e)
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
println!("please implement parse expr for {:?}", parsed.as_rule());
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_identifier(parsed: Pair<Rule>) -> Identifier {
|
||||||
|
Identifier { name: parsed.as_str().into() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_function_type(parsed: Pair<Rule>) -> Option<Type> {
|
||||||
|
let mut p = parsed.into_inner();
|
||||||
|
let parsed_params_type = p.next()?;
|
||||||
|
let parsed_return_type = p.next()?;
|
||||||
|
|
||||||
|
let params_type = parsed_params_type.into_inner().map(parse_type).collect();
|
||||||
|
let return_type = Box::new(parse_type(parsed_return_type));
|
||||||
|
Some(Type::Function(params_type, return_type))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_type(parsed: Pair<Rule>) -> Type {
|
||||||
|
match parsed.as_rule() {
|
||||||
|
Rule::type_bool => Type::Bool,
|
||||||
|
Rule::type_string => Type::String,
|
||||||
|
Rule::type_number => Type::Number,
|
||||||
|
Rule::tuple_type => {
|
||||||
|
let mut tuple = Vec::new();
|
||||||
|
let mut p = parsed.into_inner();
|
||||||
|
while let Some(t) = p.next() {
|
||||||
|
tuple.push(parse_type(t));
|
||||||
|
}
|
||||||
|
Type::Tuple(tuple)
|
||||||
|
}
|
||||||
|
Rule::type_name => {
|
||||||
|
Type::Identifier(parse_identifier(parsed))
|
||||||
|
}
|
||||||
|
Rule::function_type => {
|
||||||
|
parse_function_type(parsed).unwrap()
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
println!("implement parse type for {:?}", parsed.as_rule());
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_declaration(parsed: Pair<Rule>) -> Declaration {
|
||||||
|
match parsed.as_rule() {
|
||||||
|
Rule::type_declaration => {
|
||||||
|
let mut p = parsed.into_inner();
|
||||||
|
let identifier = p.next().unwrap();
|
||||||
|
let typ = p.next().unwrap();
|
||||||
|
|
||||||
|
let id = parse_identifier(identifier);
|
||||||
|
let t = parse_type(typ);
|
||||||
|
|
||||||
|
Declaration::Type(id, t)
|
||||||
|
},
|
||||||
|
Rule::variable_declaration => {
|
||||||
|
let mut p = parsed.into_inner();
|
||||||
|
let identifier = p.next().unwrap();
|
||||||
|
let typ = p.next().unwrap();
|
||||||
|
let definition = p.next().unwrap();
|
||||||
|
|
||||||
|
let id = parse_identifier(identifier);
|
||||||
|
let t = parse_type(typ);
|
||||||
|
let d = parse_definition(definition);
|
||||||
|
|
||||||
|
Declaration::Variable(id, t, d)
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_module_declaration(parsed: Pair<Rule>) -> Option<ModuleInformation> {
|
||||||
|
let mut p = parsed.into_inner();
|
||||||
|
let name = parse_identifier(p.next()?);
|
||||||
|
|
||||||
|
let export_import_list = p.next()?;
|
||||||
|
|
||||||
|
let mut export_list = Vec::new();
|
||||||
|
let mut import_list: HashMap<Identifier, Import> = HashMap::new();
|
||||||
|
|
||||||
|
export_import_list.into_inner().for_each(|item| {
|
||||||
|
match item.as_rule() {
|
||||||
|
Rule::module_export => {
|
||||||
|
item.into_inner().for_each(|export| {
|
||||||
|
export_list.push(parse_identifier(export))
|
||||||
|
});
|
||||||
|
}
|
||||||
|
Rule::module_import => {
|
||||||
|
let mut p = item.into_inner();
|
||||||
|
let name = parse_identifier(p.next().unwrap());
|
||||||
|
let import = {
|
||||||
|
match import_list.get_mut(&name) {
|
||||||
|
Some(import) => import,
|
||||||
|
None => {
|
||||||
|
import_list.insert(name.clone(), Import {
|
||||||
|
from: name.clone(),
|
||||||
|
rename: name.clone(),
|
||||||
|
imported: Vec::new(),
|
||||||
|
});
|
||||||
|
import_list.get_mut(&name).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if let Some(type_import) = p.next() {
|
||||||
|
match type_import.as_rule() {
|
||||||
|
Rule::import_selective => {
|
||||||
|
let imported = type_import.into_inner().map(parse_identifier).collect();
|
||||||
|
import.imported = imported;
|
||||||
|
},
|
||||||
|
Rule::import_change_name => {
|
||||||
|
import.rename = parse_identifier(type_import.into_inner().next().unwrap());
|
||||||
|
},
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
unreachable!();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let export = {
|
||||||
|
if export_list.is_empty() {
|
||||||
|
Export::All
|
||||||
|
} else {
|
||||||
|
Export::Selective(export_list)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
Some(ModuleInformation {
|
||||||
|
name,
|
||||||
|
export,
|
||||||
|
import: import_list.into_values().collect(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_module(parsed: Pair<Rule>) -> Option<Module> {
|
||||||
|
let mut p = parsed.into_inner();
|
||||||
|
|
||||||
|
let module = p.next()?;
|
||||||
|
let module_info = parse_module_declaration(module)?;
|
||||||
|
|
||||||
|
let mut declaration_list = Vec::new();
|
||||||
|
while let Some(declaration) = p.next() {
|
||||||
|
let declare = parse_declaration(declaration);
|
||||||
|
declaration_list.push(declare);
|
||||||
|
}
|
||||||
|
|
||||||
|
Some(Module {
|
||||||
|
module: module_info,
|
||||||
|
declaration: declaration_list,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
mod albireo;
|
mod albireo;
|
||||||
|
|
||||||
use crate::albireo::{AlbireoParser, Rule};
|
use crate::albireo::{AlbireoParser, Rule, parse_module};
|
||||||
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use pest::Parser;
|
use pest::Parser;
|
||||||
@ -8,10 +8,11 @@ use pest::Parser;
|
|||||||
fn main() {
|
fn main() {
|
||||||
let input = fs::read_to_string("test/simple/main.air").expect("cannot read file");
|
let input = fs::read_to_string("test/simple/main.air").expect("cannot read file");
|
||||||
|
|
||||||
let program = AlbireoParser::parse(Rule::program, &input)
|
let parsed = AlbireoParser::parse(Rule::program, &input)
|
||||||
.expect("file format is wrong or the parser is wrong")
|
.expect("file format is wrong or the parser is wrong")
|
||||||
.next()
|
.next()
|
||||||
.expect("cannot parse input file as a Albireo program");
|
.expect("cannot parse input file as a Albireo program");
|
||||||
|
|
||||||
println!("{:?}", program);
|
let module = parse_module(parsed);
|
||||||
|
println!("{:?}", module);
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,44 @@
|
|||||||
|
; declare a module
|
||||||
module main
|
module main
|
||||||
|
|
||||||
c : fn => bool = function is
|
; no explicit export so everything in this module is exported
|
||||||
let a = b in
|
export one, two
|
||||||
c(a)
|
|
||||||
|
|
||||||
b : bool = false
|
; no import
|
||||||
|
import a
|
||||||
|
import a only name, name
|
||||||
|
import a as change_name
|
||||||
|
|
||||||
a : number = 1
|
; declare a variable
|
||||||
|
one : number = 1
|
||||||
|
|
||||||
|
; declare a variable that is computed
|
||||||
|
; places a burden on the runtime
|
||||||
|
two : number = one + 1
|
||||||
|
|
||||||
|
; tt : bool = true
|
||||||
|
|
||||||
|
; types can be named, alias
|
||||||
|
|
||||||
|
; using tuple or record or enum
|
||||||
|
type coordinates_tuple = tuple (number, number)
|
||||||
|
; type coordinates_record = record { x : number , y : number }
|
||||||
|
|
||||||
|
coordinates_as_tuple : coordinates_tuple = tuple (1, 2)
|
||||||
|
; coordinates_as_record : coordinates_record = record { x : 1 , y : 2 }
|
||||||
|
|
||||||
|
; function definition is structured the same
|
||||||
|
void : fn => number = function is
|
||||||
|
let x = 1 in
|
||||||
|
1
|
||||||
|
|
||||||
|
return_false : fn => bool = function is
|
||||||
|
false
|
||||||
|
|
||||||
|
increment : fn number => number = function x is
|
||||||
|
x + 1
|
||||||
|
|
||||||
|
is_even : fn number => bool = function x is
|
||||||
|
if x % 2 then true else false
|
||||||
|
|
||||||
|
bruh : number = increment(one)
|
||||||
|
Loading…
Reference in New Issue
Block a user