Separate method definitions from method specifications in the parser.

This commit is contained in:
James Harton 2019-03-21 21:05:09 +13:00
parent dc08e056c7
commit b52e236c67
7 changed files with 277 additions and 146 deletions

View file

@ -330,26 +330,12 @@ impl Builder {
let current_ty = self.peek_ty().unwrap(); let current_ty = self.peek_ty().unwrap();
let location = context.location(&node.location()); let location = context.location(&node.location());
let (ident, args, return_type, block) = node.private_method().unwrap(); let (ident, args, block) = node.private_method().unwrap();
let method_name = context.constant_string(ident.value_ref().as_str()); let method_name = context.constant_string(ident.value_ref().as_str());
let return_type = match return_type { let return_type = context.unknown_type(location.clone());
Some(rt) => {
let types = rt
.value_ref()
.iter()
.map(|node| {
let name = context.constant_string(node.value_ref().as_str());
let location = context.location(&node.location());
context.reference_type(&name, location.clone())
})
.collect();
context.anonymous_trait(types, location.clone())
}
None => context.unknown_type(location.clone()),
};
let mut method = Method::new_private(method_name, return_type, current_ty.clone()); let mut method = Method::new_private(method_name, return_type, current_ty.clone(), location.clone());
let arguments: Vec<(StringIdx, TyIdx)> = args let arguments: Vec<(StringIdx, TyIdx)> = args
.iter() .iter()
@ -390,26 +376,12 @@ impl Builder {
let current_ty = self.peek_ty().unwrap(); let current_ty = self.peek_ty().unwrap();
let location = context.location(&node.location()); let location = context.location(&node.location());
let (ident, args, return_type, block) = node.public_method().unwrap(); let (ident, args, block) = node.public_method().unwrap();
let method_name = context.constant_string(ident.value_ref().as_str()); let method_name = context.constant_string(ident.value_ref().as_str());
let return_type = match return_type { let return_type = context.unknown_type(location.clone());
Some(rt) => {
let types = rt
.value_ref()
.iter()
.map(|node| {
let name = context.constant_string(node.value_ref().as_str());
let location = context.location(&node.location());
context.reference_type(&name, location.clone())
})
.collect();
context.anonymous_trait(types, location.clone())
}
None => context.unknown_type(location.clone()),
};
let mut method = Method::new_public(method_name, return_type, current_ty.clone()); let mut method = Method::new_public(method_name, return_type, current_ty.clone(), location.clone());
let arguments: Vec<(StringIdx, TyIdx)> = args let arguments: Vec<(StringIdx, TyIdx)> = args
.iter() .iter()
@ -446,30 +418,55 @@ impl Builder {
context.define_method(method); context.define_method(method);
} }
NodeType::StaticMethod => { NodeType::PublicMethodSpec => {
let current_ty = self.peek_ty().unwrap(); let current_ty = self.peek_ty().unwrap();
let location = context.location(&node.location()); let location = context.location(&node.location());
let (ident, args, rval) = node.public_method_spec().unwrap();
let (ident, args, return_type, block) = node.static_method().unwrap();
let method_name = context.constant_string(ident.value_ref().as_str()); let method_name = context.constant_string(ident.value_ref().as_str());
let return_type = match return_type { let types = rval
Some(rt) => {
let types = rt
.value_ref() .value_ref()
.iter() .iter()
.map(|node| { .map(|node| {
let name = context.constant_string(node.value_ref().as_str()); let name = context.constant_string(node.value_ref().as_str());
let location = context.location(&node.location()); let location = context.location(&node.location());
context.reference_type(&name, location.clone()) context.reference_type(&name, location)
}) })
.collect(); .collect();
context.anonymous_trait(types, location.clone()) let return_type = context.anonymous_trait(types, location.clone());
}
None => context.unknown_type(location.clone()),
};
let mut method = Method::new_static(method_name, return_type, current_ty.clone()); let arguments: Vec<(StringIdx, TyIdx)> = args
.iter()
.map(|(name, type_spec)| {
let name = context.constant_string(name.value_ref().as_str());
let location = context.location(&type_spec.location());
let types = type_spec
.value_ref()
.iter()
.map(|node| {
let name = context.constant_string(node.value_ref().as_str());
let location = context.location(&node.location());
context.reference_type(&name, location)
})
.collect();
let ty = context.anonymous_trait(types, location);
(name, ty)
})
.collect();
let method = Method::new_public_spec(method_name, arguments, return_type, current_ty.clone(), location);
context.define_method(method);
}
NodeType::StaticMethod => {
let current_ty = self.peek_ty().unwrap();
let location = context.location(&node.location());
let (ident, args, block) = node.static_method().unwrap();
let method_name = context.constant_string(ident.value_ref().as_str());
let return_type = context.unknown_type(location.clone());
let mut method = Method::new_static(method_name, return_type, current_ty.clone(), location);
let arguments: Vec<(StringIdx, TyIdx)> = args let arguments: Vec<(StringIdx, TyIdx)> = args
.iter() .iter()
@ -506,6 +503,44 @@ impl Builder {
context.define_method(method); context.define_method(method);
} }
NodeType::StaticMethodSpec => {
let current_ty = self.peek_ty().unwrap();
let location = context.location(&node.location());
let (ident, args, rval) = node.public_method_spec().unwrap();
let method_name = context.constant_string(ident.value_ref().as_str());
let types = rval
.value_ref()
.iter()
.map(|node| {
let name = context.constant_string(node.value_ref().as_str());
let location = context.location(&node.location());
context.reference_type(&name, location)
})
.collect();
let return_type = context.anonymous_trait(types, location.clone());
let arguments: Vec<(StringIdx, TyIdx)> = args
.iter()
.map(|(name, type_spec)| {
let name = context.constant_string(name.value_ref().as_str());
let location = context.location(&type_spec.location());
let types = type_spec
.value_ref()
.iter()
.map(|node| {
let name = context.constant_string(node.value_ref().as_str());
let location = context.location(&node.location());
context.reference_type(&name, location)
})
.collect();
let ty = context.anonymous_trait(types, location);
(name, ty)
})
.collect();
let method = Method::new_static_spec(method_name, arguments, return_type, current_ty.clone(), location);
context.define_method(method);
}
NodeType::String => { NodeType::String => {
let ty_idx = context.constant_string("Huia.Native.String"); let ty_idx = context.constant_string("Huia.Native.String");
let location = context.location(&node.location()); let location = context.location(&node.location());
@ -616,7 +651,11 @@ impl Builder {
fn peek_block(&self) -> Option<&Block> { fn peek_block(&self) -> Option<&Block> {
let len = self.blocks.len(); let len = self.blocks.len();
if len > 0 {
self.blocks.get(len - 1) self.blocks.get(len - 1)
} else {
None
}
} }
fn peek_block_mut(&mut self) -> Option<&mut Block> { fn peek_block_mut(&mut self) -> Option<&mut Block> {

View file

@ -18,6 +18,7 @@ pub fn compile_file(path: &str) -> Context {
let terms = Term::file(&contents).expect("Unable to parse file"); let terms = Term::file(&contents).expect("Unable to parse file");
let mut context = Context::new(path); let mut context = Context::new(path);
let mut builder = ir::builder::Builder::default(); let mut builder = ir::builder::Builder::default();
for term in terms { for term in terms {
builder.build(term, &mut context); builder.build(term, &mut context);
} }

View file

@ -1,14 +1,18 @@
use crate::block::BlockIdx; use crate::block::BlockIdx;
use crate::function::{Clause, ClauseIdx}; use crate::function::{Clause, ClauseIdx};
use crate::location::Location;
use crate::stable::StringIdx; use crate::stable::StringIdx;
use crate::ty::TyIdx; use crate::ty::TyIdx;
use std::collections::BTreeMap;
#[derive(Debug)] #[derive(Debug)]
pub struct Method { pub struct Method {
clauses: Vec<Clause>, clauses: Vec<Clause>,
kind: MethodKind,
location: Location,
name: StringIdx, name: StringIdx,
return_type: TyIdx, return_type: TyIdx,
kind: MethodKind, signature: BTreeMap<StringIdx, TyIdx>,
upon: TyIdx, upon: TyIdx,
} }
@ -37,32 +41,97 @@ impl Method {
} }
} }
pub fn new_public(name: StringIdx, return_type: TyIdx, upon: TyIdx) -> Method { pub fn new_private(
name: StringIdx,
return_type: TyIdx,
upon: TyIdx,
location: Location,
) -> Method {
Method { Method {
clauses: Vec::default(), clauses: Vec::default(),
name,
return_type,
kind: MethodKind::Public,
upon,
}
}
pub fn new_private(name: StringIdx, return_type: TyIdx, upon: TyIdx) -> Method {
Method {
clauses: Vec::default(),
name,
return_type,
kind: MethodKind::Private, kind: MethodKind::Private,
location,
name,
return_type,
signature: BTreeMap::default(),
upon, upon,
} }
} }
pub fn new_static(name: StringIdx, return_type: TyIdx, upon: TyIdx) -> Method { pub fn new_public(
name: StringIdx,
return_type: TyIdx,
upon: TyIdx,
location: Location,
) -> Method {
Method { Method {
clauses: Vec::default(), clauses: Vec::default(),
kind: MethodKind::Public,
location,
name, name,
return_type, return_type,
signature: BTreeMap::default(),
upon,
}
}
pub fn new_public_spec(
name: StringIdx,
arguments: Vec<(StringIdx, TyIdx)>,
return_type: TyIdx,
upon: TyIdx,
location: Location,
) -> Method {
let signature = arguments.iter().fold(BTreeMap::new(), |mut args, (k, v)| {
args.insert(k.clone(), v.clone());
args
});
Method {
clauses: Vec::default(),
kind: MethodKind::Public,
location,
name,
return_type,
signature,
upon,
}
}
pub fn new_static(
name: StringIdx,
return_type: TyIdx,
upon: TyIdx,
location: Location,
) -> Method {
Method {
clauses: Vec::default(),
kind: MethodKind::Static, kind: MethodKind::Static,
location,
name,
return_type,
signature: BTreeMap::default(),
upon,
}
}
pub fn new_static_spec(
name: StringIdx,
arguments: Vec<(StringIdx, TyIdx)>,
return_type: TyIdx,
upon: TyIdx,
location: Location,
) -> Method {
let signature = arguments.iter().fold(BTreeMap::new(), |mut args, (k, v)| {
args.insert(k.clone(), v.clone());
args
});
Method {
clauses: Vec::default(),
kind: MethodKind::Static,
location,
name,
return_type,
signature,
upon, upon,
} }
} }

View file

@ -12,6 +12,7 @@ impl StringTable {
self.0.get_or_intern(value).into() self.0.get_or_intern(value).into()
} }
#[cfg(test)]
pub fn is_empty(&self) -> bool { pub fn is_empty(&self) -> bool {
self.0.is_empty() self.0.is_empty()
} }

View file

@ -48,8 +48,10 @@ pub enum NodeType {
TraitDef, TraitDef,
ImplDef, ImplDef,
PublicMethod, PublicMethod,
PublicMethodSpec,
PrivateMethod, PrivateMethod,
StaticMethod, StaticMethod,
StaticMethodSpec,
} }
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -69,26 +71,13 @@ enum Inner {
Local(Local), Local(Local),
Map(Vec<(Term, Term)>), Map(Vec<(Term, Term)>),
MethodCall(Box<Term>, Identifier, Vec<Term>), MethodCall(Box<Term>, Identifier, Vec<Term>),
PrivateMethod( PrivateMethod(Identifier, Vec<(Identifier, TypeSpec)>, Vec<Term>),
Identifier,
Vec<(Identifier, TypeSpec)>,
Option<TypeSpec>,
Vec<Term>,
),
PropertyGet(Identifier), PropertyGet(Identifier),
PropertySet(Vec<(Identifier, Term)>), PropertySet(Vec<(Identifier, Term)>),
PublicMethod( PublicMethod(Identifier, Vec<(Identifier, TypeSpec)>, Vec<Term>),
Identifier, PublicMethodSpec(Identifier, Vec<(Identifier, TypeSpec)>, TypeSpec),
Vec<(Identifier, TypeSpec)>, StaticMethod(Identifier, Vec<(Identifier, TypeSpec)>, Vec<Term>),
Option<TypeSpec>, StaticMethodSpec(Identifier, Vec<(Identifier, TypeSpec)>, TypeSpec),
Vec<Term>,
),
StaticMethod(
Identifier,
Vec<(Identifier, TypeSpec)>,
Option<TypeSpec>,
Vec<Term>,
),
String(String), String(String),
TraitDef(Ty, Option<TypeSpec>, Vec<Term>), TraitDef(Ty, Option<TypeSpec>, Vec<Term>),
Ty(Ty), Ty(Ty),
@ -156,9 +145,11 @@ impl Term {
Inner::TypeDef(..) => NodeType::TypeDef, Inner::TypeDef(..) => NodeType::TypeDef,
Inner::TraitDef(..) => NodeType::TraitDef, Inner::TraitDef(..) => NodeType::TraitDef,
Inner::ImplDef(..) => NodeType::ImplDef, Inner::ImplDef(..) => NodeType::ImplDef,
Inner::PublicMethod(_, _, _, _) => NodeType::PublicMethod, Inner::PublicMethod(..) => NodeType::PublicMethod,
Inner::PrivateMethod(_, _, _, _) => NodeType::PrivateMethod, Inner::PublicMethodSpec(..) => NodeType::PublicMethodSpec,
Inner::StaticMethod(_, _, _, _) => NodeType::StaticMethod, Inner::PrivateMethod(..) => NodeType::PrivateMethod,
Inner::StaticMethod(..) => NodeType::StaticMethod,
Inner::StaticMethodSpec(..) => NodeType::StaticMethodSpec,
} }
} }
@ -271,16 +262,9 @@ impl Term {
pub fn private_method( pub fn private_method(
&self, &self,
) -> Option<( ) -> Option<(&Identifier, &Vec<(Identifier, TypeSpec)>, &Vec<Term>)> {
&Identifier,
&Vec<(Identifier, TypeSpec)>,
Option<&TypeSpec>,
&Vec<Term>,
)> {
match self.inner { match self.inner {
Inner::PrivateMethod(ref name, ref args, ref rval, ref body) => { Inner::PrivateMethod(ref name, ref args, ref body) => Some((name, args, body)),
Some((name, args, rval.as_ref(), body))
}
_ => None, _ => None,
} }
} }
@ -299,34 +283,34 @@ impl Term {
} }
} }
pub fn public_method( pub fn public_method(&self) -> Option<(&Identifier, &Vec<(Identifier, TypeSpec)>, &Vec<Term>)> {
&self,
) -> Option<(
&Identifier,
&Vec<(Identifier, TypeSpec)>,
Option<&TypeSpec>,
&Vec<Term>,
)> {
match self.inner { match self.inner {
Inner::PublicMethod(ref name, ref args, ref rval, ref body) => { Inner::PublicMethod(ref name, ref args, ref body) => Some((name, args, body)),
Some((name, args, rval.as_ref(), body))
}
_ => None, _ => None,
} }
} }
pub fn static_method( pub fn public_method_spec(
&self, &self,
) -> Option<( ) -> Option<(&Identifier, &Vec<(Identifier, TypeSpec)>, &TypeSpec)> {
&Identifier,
&Vec<(Identifier, TypeSpec)>,
Option<&TypeSpec>,
&Vec<Term>,
)> {
match self.inner { match self.inner {
Inner::StaticMethod(ref name, ref args, ref rval, ref body) => { Inner::PublicMethodSpec(ref name, ref args, ref rval) => Some((name, args, rval)),
Some((name, args, rval.as_ref(), body)) _ => None,
} }
}
pub fn static_method(&self) -> Option<(&Identifier, &Vec<(Identifier, TypeSpec)>, &Vec<Term>)> {
match self.inner {
Inner::StaticMethod(ref name, ref args, ref body) => Some((name, args, body)),
_ => None,
}
}
pub fn static_method_spec(
&self,
) -> Option<(&Identifier, &Vec<(Identifier, TypeSpec)>, &TypeSpec)> {
match self.inner {
Inner::StaticMethodSpec(ref name, ref args, ref rval) => Some((name, args, rval)),
_ => None, _ => None,
} }
} }
@ -455,7 +439,7 @@ impl<'a> From<Pair<'a, Rule>> for Term {
inner: Inner::Declaration(identifier, Box::new(value)), inner: Inner::Declaration(identifier, Box::new(value)),
} }
} }
Rule::defprivate => { Rule::defprivatemethod => {
let mut inner = pair.clone().into_inner(); let mut inner = pair.clone().into_inner();
let name = Identifier::from(inner.next().unwrap()); let name = Identifier::from(inner.next().unwrap());
let args = inner let args = inner
@ -469,17 +453,13 @@ impl<'a> From<Pair<'a, Rule>> for Term {
(keyword, typespec) (keyword, typespec)
}) })
.collect(); .collect();
let rval = match inner.next().unwrap().into_inner().next() {
Some(value) => Some(TypeSpec::from(value)),
_ => None,
};
let block = inner.next().unwrap().into_inner().map(Term::from).collect(); let block = inner.next().unwrap().into_inner().map(Term::from).collect();
Term { Term {
location: InputLocation::from(pair), location: InputLocation::from(pair),
inner: Inner::PrivateMethod(name, args, rval, block), inner: Inner::PrivateMethod(name, args, block),
} }
} }
Rule::defpublic => { Rule::defpublicmethod => {
let mut inner = pair.clone().into_inner(); let mut inner = pair.clone().into_inner();
let name = Identifier::from(inner.next().unwrap()); let name = Identifier::from(inner.next().unwrap());
let args = inner let args = inner
@ -493,17 +473,33 @@ impl<'a> From<Pair<'a, Rule>> for Term {
(keyword, typespec) (keyword, typespec)
}) })
.collect(); .collect();
let rval = match inner.next().unwrap().into_inner().next() {
Some(value) => Some(TypeSpec::from(value)),
_ => None,
};
let block = inner.next().unwrap().into_inner().map(Term::from).collect(); let block = inner.next().unwrap().into_inner().map(Term::from).collect();
Term { Term {
location: InputLocation::from(pair), location: InputLocation::from(pair),
inner: Inner::PublicMethod(name, args, rval, block), inner: Inner::PublicMethod(name, args, block),
} }
} }
Rule::defstatic => { Rule::defpublicspec => {
let mut inner = pair.clone().into_inner();
let name = Identifier::from(inner.next().unwrap());
let args = inner
.next()
.unwrap()
.into_inner()
.map(|p| {
let mut inner = p.into_inner();
let keyword = Identifier::from(inner.next().unwrap());
let typespec = TypeSpec::from(inner.next().unwrap());
(keyword, typespec)
})
.collect();
let rval = TypeSpec::from(inner.next().unwrap().into_inner().next().unwrap());
Term {
location: InputLocation::from(pair),
inner: Inner::PublicMethodSpec(name, args, rval),
}
}
Rule::defstaticmethod => {
let mut inner = pair.clone().into_inner(); let mut inner = pair.clone().into_inner();
let name = Identifier::from(inner.next().unwrap()); let name = Identifier::from(inner.next().unwrap());
let args = inner let args = inner
@ -517,14 +513,30 @@ impl<'a> From<Pair<'a, Rule>> for Term {
(keyword, typespec) (keyword, typespec)
}) })
.collect(); .collect();
let rval = match inner.next().unwrap().into_inner().next() {
Some(value) => Some(TypeSpec::from(value)),
_ => None,
};
let block = inner.next().unwrap().into_inner().map(Term::from).collect(); let block = inner.next().unwrap().into_inner().map(Term::from).collect();
Term { Term {
location: InputLocation::from(pair), location: InputLocation::from(pair),
inner: Inner::StaticMethod(name, args, rval, block), inner: Inner::StaticMethod(name, args, block),
}
}
Rule::defstaticspec => {
let mut inner = pair.clone().into_inner();
let name = Identifier::from(inner.next().unwrap());
let args = inner
.next()
.unwrap()
.into_inner()
.map(|p| {
let mut inner = p.into_inner();
let keyword = Identifier::from(inner.next().unwrap());
let typespec = TypeSpec::from(inner.next().unwrap());
(keyword, typespec)
})
.collect();
let rval = TypeSpec::from(inner.next().unwrap().into_inner().next().unwrap());
Term {
location: InputLocation::from(pair),
inner: Inner::StaticMethodSpec(name, args, rval),
} }
} }
Rule::float => Term { Rule::float => Term {
@ -876,10 +888,9 @@ mod test {
assert_eq!(key.value_ref(), "speed"); assert_eq!(key.value_ref(), "speed");
assert_eq!(value.value_ref()[0].value_ref(), "Integer"); assert_eq!(value.value_ref()[0].value_ref(), "Integer");
let (name, args, rval, block) = &body[0].static_method().unwrap(); let (name, args, block) = &body[0].static_method().unwrap();
assert_eq!(name.value_ref(), "new"); assert_eq!(name.value_ref(), "new");
assert!(args.is_empty()); assert!(args.is_empty());
assert!(rval.is_none());
assert_eq!(block.len(), 1); assert_eq!(block.len(), 1);
} }

View file

@ -37,7 +37,10 @@ impl<'a> From<Pair<'a, Rule>> for TypeSpec {
location: InputLocation::from(pair.into_span()), location: InputLocation::from(pair.into_span()),
} }
} }
_ => unreachable!("Expected pair to be an TypeSpec"), _ => unreachable!(
"Expected pair to be an TypeSpec but was a {:?}",
pair.as_rule()
),
} }
} }
} }

View file

@ -2,8 +2,11 @@ input = _{ SOI ~ expression+ ~ EOI }
file = _{ SOI ~ definition* ~ EOI } file = _{ SOI ~ definition* ~ EOI }
WHITESPACE = _{ (" " | "\t" | "\r" | "\n")+ } WHITESPACE = _{ (" " | "\t" | "\r" | "\n")+ }
COMMENT = _{ comment_block | comment_line }
comment_block = @{ "###" ~ (!"###" ~ ANY)* ~ "###" }
comment_line = @{ "#" ~ (!("\r" | "\n") ~ ANY)* }
newline = _{ (" " | "\t")* ~ ("\n" | "\r")+ ~ (" " | "\t")* } newline = _{ (" " | "\t")* ~ ("\n" | "\r")+ ~ (" " | "\t")* }
reserved = { "end" | "let" | "true" | "false" | "else" } reserved = { "end" | "let" | "true" | "false" | "else" | "def" | "defp" | "defs" | "do" }
expression = _{ infix | expression_inner } expression = _{ infix | expression_inner }
infix = { expression_inner ~ (binary_operator ~ expression_inner)+ } infix = { expression_inner ~ (binary_operator ~ expression_inner)+ }
@ -45,27 +48,31 @@ typedefblock = { ("do" ~ (methoddef | impldef)* ~ "end")? }
traitdef = { "trait" ~ typename ~ traitdefreqs ~ traitdefblock } traitdef = { "trait" ~ typename ~ traitdefreqs ~ traitdefblock }
traitdefreqs = { (":" ~ typespec)? } traitdefreqs = { (":" ~ typespec)? }
traitdefblock = { ("do" ~ methoddef* ~ "end")? } traitdefblock = { ("do" ~ (methoddef | methodspec)* ~ "end")? }
impldef = { "impl" ~ typename ~ impldefblock } impldef = { "impl" ~ typename ~ impldefblock }
impldefblock = { ("do" ~ methoddef* ~ "end")? } impldefblock = { ("do" ~ methoddef* ~ "end")? }
methoddef = _{ defpublic | defprivate | defstatic } methoddef = _{ defpublicmethod | defprivatemethod | defstaticmethod }
methodspec = _{ defpublicspec | defstaticspec }
methodargs = { defargs? } methodargs = { defargs? }
methodname = @{ ident ~ ("?")? } methodname = @{ ident ~ ("?")? }
methodblockstatic = { "do" ~ expression* ~ "end" } methodblockstatic = { "do" ~ expression* ~ "end" }
methodblockinstance = { "do" ~ instance_espression* ~ "end" } methodblockinstance = { "do" ~ instance_espression* ~ "end" }
methodrval = { (":" ~ typespec)? } methodrval = { ":" ~ typespec }
defpublic = { "def" ~ methodname ~ methodargs ~ methodrval ~ methodblockinstance } defpublicmethod = { "def" ~ methodname ~ methodargs ~ methodblockinstance }
defprivate = { "defp" ~ methodname ~ methodargs ~ methodrval ~ methodblockinstance } defprivatemethod = { "defp" ~ methodname ~ methodargs ~ methodblockinstance }
defstatic = { "defs" ~ methodname ~ methodargs ~ methodrval ~ methodblockstatic } defstaticmethod = { "defs" ~ methodname ~ methodargs ~ methodblockstatic }
defpublicspec = { "def" ~ methodname ~ methodargs ~ methodrval }
defstaticspec = { "defs" ~ methodname ~ methodargs ~ methodrval }
typespec = { typename ~ ("+" ~ typename)* } typespec = { typename ~ ("+" ~ typename)* }
literal = _{ constructor | map | array | typename | string | atom | float | integer | boolean } literal = _{ constructor | map | array | typename | string | atom | float | integer | boolean }
ident = @{ !reserved ~ 'a'..'z' ~ ('a'..'z' | 'A'..'Z' | "_")* } ident = @{ !reserved ~ LOWERCASE_LETTER ~ (LETTER | "_")* }
keyword = @{ ident ~ ":" } keyword = @{ ident ~ ":" }
if_expression = { "if" ~ instance_espression ~ if_positive ~ if_negative? ~ "end" } if_expression = { "if" ~ instance_espression ~ if_positive ~ if_negative? ~ "end" }
@ -87,7 +94,7 @@ array = { "[" ~ (expression ~ ("," ~ expression)*)? ~ "]"
atom = @{ ":" ~ ident } atom = @{ ":" ~ ident }
typename = @{ typename_name ~ ("." ~ typename_name)* } typename = @{ typename_name ~ ("." ~ typename_name)* }
typename_name = @{ 'A'..'Z' ~ ('a'..'z' | 'A'..'Z' | "_")* } typename_name = @{ UPPERCASE_LETTER ~ (LETTER | "_")* }
function = { "fn" ~ function_clause ~ ("," ~ function_clause)* } function = { "fn" ~ function_clause ~ ("," ~ function_clause)* }
function_args = { defargs } function_args = { defargs }