2017-09-18 19:09:27 -07:00
use itertools ::Itertools ;
2017-09-07 19:38:22 -07:00
use std ::collections ::HashMap ;
2017-08-29 05:08:09 -07:00
use std ::rc ::Rc ;
2017-09-06 05:09:20 -07:00
use std ::iter ::{ Enumerate , Peekable } ;
2017-09-09 01:25:11 -07:00
use std ::vec ::IntoIter ;
2017-09-06 05:09:20 -07:00
use std ::str ::Chars ;
2017-08-29 04:27:07 -07:00
2017-09-09 01:25:11 -07:00
#[ derive(Debug, PartialEq, Clone) ]
2017-09-04 12:17:20 -07:00
pub enum TokenType {
2017-09-06 05:09:20 -07:00
Newline , Semicolon ,
2017-09-04 12:17:20 -07:00
2017-09-06 05:09:20 -07:00
LParen , RParen ,
LSquareBracket , RSquareBracket ,
LAngleBracket , RAngleBracket ,
LCurlyBrace , RCurlyBrace ,
2017-09-07 22:29:23 -07:00
Pipe ,
2017-09-04 12:17:20 -07:00
2017-09-06 05:09:20 -07:00
Comma , Period , Colon , Underscore ,
2017-09-04 12:17:20 -07:00
2017-09-06 05:09:20 -07:00
Operator ( Rc < String > ) ,
2018-01-08 06:12:45 -08:00
DigitGroup ( Rc < String > ) , HexLiteral ( Rc < String > ) , BinNumberSigil ,
2017-08-29 05:08:09 -07:00
StrLiteral ( Rc < String > ) ,
Identifier ( Rc < String > ) ,
2017-09-04 12:17:20 -07:00
Keyword ( Kw ) ,
2017-09-06 05:09:20 -07:00
2017-09-11 02:07:17 -07:00
EOF ,
2017-09-06 05:09:20 -07:00
Error ( String ) ,
2017-08-29 05:08:09 -07:00
}
2017-09-11 03:13:19 -07:00
use self ::TokenType ::* ;
2017-08-29 05:08:09 -07:00
2017-09-08 02:43:03 -07:00
#[ derive(Debug, Clone, Copy, PartialEq) ]
2017-09-04 12:17:20 -07:00
pub enum Kw {
2017-09-07 22:29:23 -07:00
If , Else ,
2017-09-04 12:17:20 -07:00
Func ,
2017-09-06 05:09:20 -07:00
For ,
2017-09-07 23:40:42 -07:00
Match ,
Var , Const , Let , In ,
2017-09-17 06:22:19 -07:00
Return ,
2017-09-07 23:40:42 -07:00
Alias , Type , SelfType , SelfIdent ,
2017-09-07 22:29:23 -07:00
Trait , Impl ,
2017-10-22 03:58:09 -07:00
True , False ,
Module
2017-09-04 12:17:20 -07:00
}
2017-09-11 03:13:19 -07:00
use self ::Kw ::* ;
2017-09-04 12:17:20 -07:00
2017-09-07 19:38:22 -07:00
lazy_static! {
static ref KEYWORDS : HashMap < & 'static str , Kw > =
hashmap! {
" if " = > Kw ::If ,
" else " = > Kw ::Else ,
2017-09-07 22:29:23 -07:00
" fn " = > Kw ::Func ,
" for " = > Kw ::For ,
2017-09-07 23:40:42 -07:00
" match " = > Kw ::Match ,
2017-09-07 22:29:23 -07:00
" var " = > Kw ::Var ,
" const " = > Kw ::Const ,
" let " = > Kw ::Let ,
2017-09-07 23:40:42 -07:00
" in " = > Kw ::In ,
2017-09-17 06:22:19 -07:00
" return " = > Kw ::Return ,
2017-09-07 23:40:42 -07:00
" alias " = > Kw ::Alias ,
2017-09-07 22:29:23 -07:00
" type " = > Kw ::Type ,
" Self " = > Kw ::SelfType ,
" self " = > Kw ::SelfIdent ,
" trait " = > Kw ::Trait ,
" impl " = > Kw ::Impl ,
" true " = > Kw ::True ,
" false " = > Kw ::False ,
2017-10-22 03:58:09 -07:00
" module " = > Kw ::Module ,
2017-09-07 19:38:22 -07:00
} ;
}
2017-09-04 12:17:20 -07:00
#[ derive(Debug) ]
pub struct Token {
2017-09-18 19:09:27 -07:00
pub token_type : TokenType ,
pub offset : usize ,
2017-09-04 12:17:20 -07:00
}
2017-09-06 23:52:25 -07:00
impl Token {
pub fn get_error ( & self ) -> Option < & String > {
match self . token_type {
TokenType ::Error ( ref s ) = > Some ( s ) ,
_ = > None ,
}
}
}
2017-09-06 05:09:20 -07:00
fn is_digit ( c : & char ) -> bool {
c . is_digit ( 10 )
}
2017-09-17 02:38:11 -07:00
const OPERATOR_CHARS : [ char ; 19 ] = [ '!' , '$' , '%' , '&' , '*' , '+' , '-' , '.' , '/' , ':' , '<' , '>' , '=' , '?' , '@' , '^' , '|' , '~' , '`' ] ;
fn is_operator ( c : & char ) -> bool {
OPERATOR_CHARS . iter ( ) . any ( | x | x = = c )
}
2017-09-06 05:09:20 -07:00
type CharIter < ' a > = Peekable < Enumerate < Chars < ' a > > > ;
2017-09-06 23:52:25 -07:00
pub fn tokenize ( input : & str ) -> Vec < Token > {
2017-09-06 05:09:20 -07:00
let mut tokens : Vec < Token > = Vec ::new ( ) ;
let mut input : CharIter = input . chars ( ) . enumerate ( ) . peekable ( ) ;
while let Some ( ( idx , c ) ) = input . next ( ) {
let cur_tok_type = match c {
'#' = > {
if let Some ( & ( _ , '{' ) ) = input . peek ( ) {
} else {
while let Some ( ( _ , c ) ) = input . next ( ) {
if c = = '\n' {
break ;
}
}
}
continue ;
} ,
2017-09-07 22:29:23 -07:00
c if c . is_whitespace ( ) & & c ! = '\n' = > continue ,
2017-09-06 05:09:20 -07:00
'\n' = > Newline , ';' = > Semicolon ,
2017-09-17 04:26:44 -07:00
':' = > Colon , ',' = > Comma ,
2017-09-06 05:09:20 -07:00
'(' = > LParen , ')' = > RParen ,
'{' = > LCurlyBrace , '}' = > RCurlyBrace ,
'[' = > LSquareBracket , ']' = > RSquareBracket ,
2017-09-06 09:42:29 -07:00
'"' = > handle_quote ( & mut input ) ,
2017-09-06 05:09:20 -07:00
c if is_digit ( & c ) = > handle_digit ( c , & mut input ) ,
2017-09-08 01:33:27 -07:00
c if c . is_alphabetic ( ) | | c = = '_' = > handle_alphabetic ( c , & mut input ) , //TODO I'll probably have to rewrite this if I care about types being uppercase, also type parameterization
2017-09-17 02:38:11 -07:00
c if is_operator ( & c ) = > handle_operator ( c , & mut input ) ,
unknown = > Error ( format! ( " Unexpected character: {} " , unknown ) ) ,
2017-09-06 05:09:20 -07:00
} ;
tokens . push ( Token { token_type : cur_tok_type , offset : idx } ) ;
}
2017-09-06 23:52:25 -07:00
tokens
2017-09-06 05:09:20 -07:00
}
fn handle_digit ( c : char , input : & mut CharIter ) -> TokenType {
if c = = '0' & & input . peek ( ) . map_or ( false , | & ( _ , c ) | { c = = 'x' } ) {
input . next ( ) ;
2018-01-08 06:12:45 -08:00
let rest : String = input . peeking_take_while ( | & ( _ , ref c ) | c . is_digit ( 16 ) | | * c = = '_' ) . map ( | ( _ , c ) | { c } ) . collect ( ) ;
HexLiteral ( Rc ::new ( rest ) )
2017-09-06 05:09:20 -07:00
} else if c = = '0' & & input . peek ( ) . map_or ( false , | & ( _ , c ) | { c = = 'b' } ) {
input . next ( ) ;
BinNumberSigil
} else {
let mut buf = c . to_string ( ) ;
buf . extend ( input . peeking_take_while ( | & ( _ , ref c ) | is_digit ( c ) ) . map ( | ( _ , c ) | { c } ) ) ;
DigitGroup ( Rc ::new ( buf ) )
}
2017-08-29 05:08:09 -07:00
}
2017-09-06 09:42:29 -07:00
fn handle_quote ( input : & mut CharIter ) -> TokenType {
2017-09-06 16:52:49 -07:00
let mut buf = String ::new ( ) ;
2017-09-07 00:18:36 -07:00
loop {
match input . next ( ) . map ( | ( _ , c ) | { c } ) {
Some ( '"' ) = > break ,
Some ( '\\' ) = > {
let next = input . peek ( ) . map ( | & ( _ , c ) | { c } ) ;
if next = = Some ( 'n' ) {
input . next ( ) ;
buf . push ( '\n' )
} else if next = = Some ( '"' ) {
input . next ( ) ;
buf . push ( '"' ) ;
} else if next = = Some ( 't' ) {
input . next ( ) ;
buf . push ( '\t' ) ;
}
} ,
Some ( c ) = > buf . push ( c ) ,
None = > return TokenType ::Error ( format! ( " Unclosed string " ) ) ,
2017-09-06 16:52:49 -07:00
}
}
TokenType ::StrLiteral ( Rc ::new ( buf ) )
2017-09-06 09:42:29 -07:00
}
fn handle_alphabetic ( c : char , input : & mut CharIter ) -> TokenType {
2017-09-07 19:38:22 -07:00
let mut buf = String ::new ( ) ;
buf . push ( c ) ;
2017-09-08 01:33:27 -07:00
if c = = '_' & & input . peek ( ) . map ( | & ( _ , c ) | { ! c . is_alphabetic ( ) } ) . unwrap_or ( true ) {
2017-09-11 02:07:17 -07:00
return TokenType ::Underscore
2017-09-08 01:33:27 -07:00
}
2017-09-07 19:38:22 -07:00
loop {
match input . peek ( ) . map ( | & ( _ , c ) | { c } ) {
Some ( c ) if c . is_alphanumeric ( ) = > {
input . next ( ) ;
buf . push ( c ) ;
} ,
_ = > break ,
}
}
match KEYWORDS . get ( buf . as_str ( ) ) {
Some ( kw ) = > TokenType ::Keyword ( kw . clone ( ) ) ,
None = > TokenType ::Identifier ( Rc ::new ( buf ) ) ,
}
2017-09-06 09:42:29 -07:00
}
fn handle_operator ( c : char , input : & mut CharIter ) -> TokenType {
2017-09-17 02:38:11 -07:00
match c {
2017-09-17 04:26:44 -07:00
'<' | '>' | '|' | '.' = > {
2017-09-17 02:38:11 -07:00
let ref next = input . peek ( ) . map ( | & ( _ , c ) | { c } ) ;
if ! next . map ( | n | { is_operator ( & n ) } ) . unwrap_or ( false ) {
return match c {
'<' = > LAngleBracket ,
'>' = > RAngleBracket ,
'|' = > Pipe ,
2017-09-17 04:26:44 -07:00
'.' = > Period ,
2017-09-17 02:38:11 -07:00
_ = > unreachable! ( ) ,
}
}
} ,
_ = > ( ) ,
} ;
2017-09-07 22:29:23 -07:00
let mut buf = String ::new ( ) ;
buf . push ( c ) ;
loop {
match input . peek ( ) . map ( | & ( _ , c ) | { c } ) {
2017-09-17 02:38:11 -07:00
Some ( c ) if is_operator ( & c ) = > {
2017-09-07 22:29:23 -07:00
input . next ( ) ;
buf . push ( c ) ;
} ,
_ = > break
}
}
TokenType ::Operator ( Rc ::new ( buf ) )
2017-09-06 09:42:29 -07:00
}
2017-09-08 02:43:03 -07:00
#[ cfg(test) ]
mod schala_tokenizer_tests {
use super ::* ;
2017-09-11 02:07:17 -07:00
macro_rules ! digit { ( $ident :expr ) = > { DigitGroup ( Rc ::new ( $ident . to_string ( ) ) ) } }
2017-09-08 02:43:03 -07:00
macro_rules ! ident { ( $ident :expr ) = > { Identifier ( Rc ::new ( $ident . to_string ( ) ) ) } }
macro_rules ! op { ( $ident :expr ) = > { Operator ( Rc ::new ( $ident . to_string ( ) ) ) } }
2017-09-12 00:48:37 -07:00
2017-09-08 02:43:03 -07:00
#[ test ]
fn tokens ( ) {
let a = tokenize ( " let a: A<B> = c ++ d " ) ;
let token_types : Vec < TokenType > = a . into_iter ( ) . map ( move | t | t . token_type ) . collect ( ) ;
assert_eq! ( token_types , vec! [ Keyword ( Let ) , ident! ( " a " ) , Colon , ident! ( " A " ) ,
LAngleBracket , ident! ( " B " ) , RAngleBracket , op! ( " = " ) , ident! ( " c " ) , op! ( " ++ " ) , ident! ( " d " ) ] ) ;
}
2017-09-11 02:07:17 -07:00
#[ test ]
fn underscores ( ) {
let token_types : Vec < TokenType > = tokenize ( " 4_8 " ) . into_iter ( ) . map ( move | t | t . token_type ) . collect ( ) ;
assert_eq! ( token_types , vec! [ digit! ( " 4 " ) , Underscore , digit! ( " 8 " ) ] ) ;
}
2017-09-08 02:43:03 -07:00
}
2017-09-06 09:42:29 -07:00
2017-09-11 02:07:17 -07:00
/* Schala EBNF Grammar */
2017-09-17 00:04:27 -07:00
/* Terminal productions are in 'single quotes' or UPPERCASE if they are a class
2017-09-13 22:40:05 -07:00
* or not representable in ASCII
2017-09-11 02:07:17 -07:00
program := ( statement delimiter ) * EOF
2017-09-17 00:04:27 -07:00
delimiter := NEWLINE | ';'
2017-09-11 02:07:17 -07:00
statement := expression | declaration
2017-10-04 22:02:31 -07:00
declaration := type_declaration | func_declaration | binding_declaration | impl_declaration
2017-09-11 02:07:17 -07:00
2017-10-04 22:02:31 -07:00
type_declaration := ' type ' type_declaration_body
type_declaration_body := ' alias ' type_alias | IDENTIFIER '=' type_body
2017-10-08 18:47:57 -07:00
type_alias := IDENTIFIER '=' type_name
2017-09-17 00:04:27 -07:00
type_body := variant_specifier ( '|' variant_specifier ) *
2017-10-08 18:47:57 -07:00
2017-10-08 19:02:52 -07:00
variant_specifier := IDENTIFIER | IDENTIFIER '{' typed_identifier_list '}' | IDENTIFIER '(' type_name * ')'
typed_identifier_list := typed_identifier *
typed_identifier := IDENTIFIER type_anno
2017-09-11 20:37:19 -07:00
2017-10-08 21:21:02 -07:00
func_declaration := func_signature func_body
func_body := ε | '{' ( statement delimiter ) * '}'
func_signature := ' fn ' IDENTIFIER formal_param_list func_body
2017-10-08 20:55:05 -07:00
formal_param_list := '(' ( formal_param ',' ) * ')'
formal_param := IDENTIFIER type_anno +
2017-09-11 02:07:17 -07:00
2017-09-17 06:04:24 -07:00
binding_declaration : ' var ' IDENTIFIER '=' expression
| ' const ' IDENTIFIER '=' expression
2017-10-03 03:49:07 -07:00
trait_declaration := ' trait ' trait_name decl_block
impl_declaration := ' impl ' IDENTIFIER decl_block | ' impl ' trait_name ' for ' IDENTIFIER decl_block
2017-10-08 14:24:02 -07:00
decl_block := '{' ( func_declaration ) * '}'
2017-10-03 03:49:07 -07:00
trait_name := IDENTIFIER
2017-09-28 23:55:10 -07:00
type_anno := ( ':' type_name ) +
type_name := IDENTIFIER ( type_params ) * | '(' type_names ')'
type_names := ε | type_name ( , type_name ) *
type_params := '<' type_name ( , type_name ) * '>'
2017-09-11 23:16:37 -07:00
2017-09-26 22:10:13 -07:00
expression := precedence_expr type_anno +
2017-09-17 17:44:06 -07:00
precedence_expr := prefix_expr
prefix_expr := prefix_op primary
prefix_op := '+' | '-' | '!' | '~'
2017-10-08 22:02:58 -07:00
primary := literal | paren_expr | if_expr | match_expr | for_expr | identifier_expr
2017-09-13 22:40:05 -07:00
2017-10-06 20:28:07 -07:00
paren_expr := LParen paren_inner RParen
paren_inner := ( expression ',' ) *
2017-10-13 18:56:02 -07:00
identifier_expr := named_struct | call_expr | index_expr | IDENTIFIER
2017-09-17 00:04:27 -07:00
literal := ' true ' | ' false ' | number_literal | STR_LITERAL
2017-09-11 02:07:17 -07:00
2017-10-13 18:56:02 -07:00
named_struct := IDENTIFIER record_block
2017-10-14 13:54:17 -07:00
record_block := '{' ( record_entry , ',' ) * | '}' //TODO support anonymus structs, update syntax
record_entry := IDENTIFIER ':' expression
2017-10-13 18:56:02 -07:00
2017-09-18 23:22:28 -07:00
if_expr := ' if ' expression block else_clause
else_clause := ε | ' else ' block
2017-09-30 14:11:38 -07:00
match_expr := ' match ' expression match_body
match_body := '{' ( match_arm ) * '}'
match_arm := pattern ' = > ' expression
2017-09-21 16:00:14 -07:00
pattern := identifier //TODO NOT DONE
2017-09-20 20:30:30 -07:00
2017-09-18 23:22:28 -07:00
block := '{' ( statement ) * '}'
2017-09-17 00:04:27 -07:00
call_expr := IDENTIFIER '(' expr_list ')' //TODO maybe make this optional? or no, have a bare identifier meant to be used as method taken care of in eval
index_expr := '[' ( expression ( ',' ( expression ) * | ε ) ']'
expr_list := expression ( ',' expression ) * | ε
2017-09-11 15:42:49 -07:00
2017-10-08 22:02:58 -07:00
for_expr := ' for ' .. . ? ? ? ?
2017-09-18 23:22:28 -07:00
2017-09-11 02:07:17 -07:00
// a float_literal can still be assigned to an int in type-checking
number_literal := int_literal | float_literal
2017-09-13 22:40:05 -07:00
int_literal = ( ' 0 x ' | ' 0 b ' ) digits
float_literal := digits ( '.' digits )
digits := ( DIGIT_GROUP underscore ) +
2017-09-11 02:07:17 -07:00
* /
2017-09-09 01:25:11 -07:00
type TokenIter = Peekable < IntoIter < Token > > ;
2017-09-30 13:04:56 -07:00
#[ derive(Debug, PartialEq) ]
2017-09-11 02:07:17 -07:00
pub struct ParseError {
pub msg : String ,
}
impl ParseError {
fn new < T > ( msg : & str ) -> ParseResult < T > {
Err ( ParseError { msg : msg . to_string ( ) } )
}
}
pub type ParseResult < T > = Result < T , ParseError > ;
2017-09-15 16:35:45 -07:00
#[ derive(Debug) ]
2017-09-17 05:06:58 -07:00
pub struct ParseRecord {
production_name : String ,
next_token : String ,
2018-02-10 15:10:06 -08:00
level : u32 ,
2017-09-17 05:06:58 -07:00
}
2017-09-15 04:23:39 -07:00
2017-09-08 16:42:42 -07:00
struct Parser {
2017-09-09 01:25:11 -07:00
tokens : TokenIter ,
2017-09-15 04:23:39 -07:00
parse_record : Vec < ParseRecord > ,
2018-02-10 15:10:06 -08:00
parse_level : u32
2017-09-09 01:25:11 -07:00
}
impl Parser {
fn new ( input : Vec < Token > ) -> Parser {
2018-02-10 15:10:06 -08:00
Parser { tokens : input . into_iter ( ) . peekable ( ) , parse_record : vec ! [ ] , parse_level : 0 }
2017-09-09 01:25:11 -07:00
}
2017-09-11 02:07:17 -07:00
fn peek ( & mut self ) -> TokenType {
self . tokens . peek ( ) . map ( | ref t | { t . token_type . clone ( ) } ) . unwrap_or ( TokenType ::EOF )
2017-09-09 01:27:15 -07:00
}
2017-09-11 02:07:17 -07:00
fn next ( & mut self ) -> TokenType {
self . tokens . next ( ) . map ( | ref t | { t . token_type . clone ( ) } ) . unwrap_or ( TokenType ::EOF )
2017-09-09 01:25:11 -07:00
}
2017-09-08 16:42:42 -07:00
}
2017-09-11 02:07:17 -07:00
macro_rules ! expect {
2017-09-30 14:41:37 -07:00
( $self :expr , $token_type :pat , $expected_item :expr ) = > { expect! ( $self , $token_type if true , $expected_item ) } ;
( $self :expr , $token_type :pat if $cond :expr , $expected_item :expr ) = > {
2017-09-13 22:40:05 -07:00
match $self . peek ( ) {
$token_type if $cond = > $self . next ( ) ,
2017-09-30 14:41:37 -07:00
tok = > {
let msg = format! ( " Expected {} , got {:?} " , $expected_item , tok ) ;
return Err ( ParseError { msg } )
}
2017-09-13 22:40:05 -07:00
}
2017-09-11 02:07:17 -07:00
}
2017-09-09 00:31:15 -07:00
}
2017-09-11 03:21:07 -07:00
#[ derive(Debug, PartialEq) ]
2017-10-01 12:55:28 -07:00
pub struct AST ( pub Vec < Statement > ) ;
2017-09-08 16:42:42 -07:00
2017-10-08 13:51:56 -07:00
#[ derive(Debug, PartialEq, Clone) ]
2017-09-08 16:42:42 -07:00
pub enum Statement {
2017-09-28 00:06:08 -07:00
ExpressionStatement ( Expression ) ,
2017-09-08 16:42:42 -07:00
Declaration ( Declaration ) ,
}
2017-09-13 23:04:45 -07:00
type ParamName = Rc < String > ;
2017-10-03 03:49:07 -07:00
type TraitName = Rc < String > ;
2017-10-08 20:55:05 -07:00
type FormalParam = ( ParamName , Option < TypeName > ) ;
2017-09-13 23:04:45 -07:00
2017-10-08 13:51:56 -07:00
#[ derive(Debug, PartialEq, Clone) ]
2017-09-08 16:42:42 -07:00
pub enum Declaration {
2017-10-08 21:21:02 -07:00
FuncSig ( Signature ) ,
FuncDecl ( Signature , Vec < Statement > ) ,
2017-09-13 22:40:05 -07:00
TypeDecl ( Rc < String > , TypeBody ) ,
2017-09-17 06:04:24 -07:00
TypeAlias ( Rc < String > , Rc < String > ) ,
Binding {
name : Rc < String > ,
constant : bool ,
expr : Expression ,
2017-10-03 03:49:07 -07:00
} ,
Impl {
type_name : TypeName ,
trait_name : Option < TraitName > ,
block : Vec < Declaration > ,
} ,
2017-09-11 15:42:49 -07:00
}
2017-10-08 21:21:02 -07:00
#[ derive(Debug, PartialEq, Clone) ]
pub struct Signature {
2017-10-09 02:26:59 -07:00
pub name : Rc < String > ,
pub params : Vec < FormalParam > ,
pub type_anno : Option < TypeName > ,
2017-10-08 21:21:02 -07:00
}
2017-10-08 13:51:56 -07:00
#[ derive(Debug, PartialEq, Clone) ]
2017-10-01 12:55:28 -07:00
pub struct TypeBody ( pub Vec < Variant > ) ;
2017-09-13 22:40:05 -07:00
2017-10-08 13:51:56 -07:00
#[ derive(Debug, PartialEq, Clone) ]
2017-09-13 22:40:05 -07:00
pub enum Variant {
2017-10-08 19:15:08 -07:00
UnitStruct ( Rc < String > ) ,
2017-10-08 19:30:52 -07:00
TupleStruct ( Rc < String > , Vec < TypeName > ) ,
Record ( Rc < String > , Vec < ( Rc < String > , TypeName ) > ) ,
2017-09-08 16:42:42 -07:00
}
2017-10-08 13:51:56 -07:00
#[ derive(Debug, PartialEq, Clone) ]
2017-10-08 19:30:52 -07:00
pub struct Expression ( pub ExpressionType , pub Option < TypeName > ) ;
2017-09-27 22:27:50 -07:00
2017-10-08 13:51:56 -07:00
#[ derive(Debug, PartialEq, Clone) ]
2017-10-08 19:30:52 -07:00
pub enum TypeName {
Tuple ( Vec < TypeName > ) ,
2017-09-28 23:55:10 -07:00
Singleton {
name : Rc < String > ,
2017-10-08 19:30:52 -07:00
params : Vec < TypeName > ,
2017-09-28 23:55:10 -07:00
}
}
2017-09-27 22:27:50 -07:00
2017-10-08 13:51:56 -07:00
#[ derive(Debug, PartialEq, Clone) ]
2017-09-27 22:27:50 -07:00
pub enum ExpressionType {
2017-09-11 03:10:10 -07:00
IntLiteral ( u64 ) ,
2017-09-08 16:42:42 -07:00
FloatLiteral ( f64 ) ,
2017-09-16 15:57:48 -07:00
StringLiteral ( Rc < String > ) ,
2017-09-17 04:31:27 -07:00
BoolLiteral ( bool ) ,
2017-09-13 20:10:06 -07:00
BinExp ( Operation , Box < Expression > , Box < Expression > ) ,
2017-09-17 17:44:06 -07:00
PrefixExp ( Operation , Box < Expression > ) ,
2017-10-06 20:28:07 -07:00
TupleLiteral ( Vec < Expression > ) ,
2017-10-14 13:54:17 -07:00
Value ( Rc < String > , Vec < ( Rc < String > , Expression ) > ) ,
2017-09-13 20:10:06 -07:00
Call {
2017-10-08 23:02:03 -07:00
f : Box < Expression > ,
2017-10-08 22:52:05 -07:00
arguments : Vec < Expression > ,
2017-09-14 00:11:52 -07:00
} ,
Index {
indexee : Box < Expression > ,
indexers : Vec < Expression > ,
2017-09-18 23:22:28 -07:00
} ,
IfExpression ( Box < Expression > , Vec < Statement > , Option < Vec < Statement > > ) ,
2017-10-08 22:02:58 -07:00
MatchExpression ( Box < Expression > , Vec < MatchArm > ) ,
ForExpression
2017-09-12 02:30:27 -07:00
}
2017-10-08 13:51:56 -07:00
#[ derive(Debug, PartialEq, Clone) ]
2017-09-20 21:05:08 -07:00
pub struct MatchArm {
pat : Pattern ,
expr : Expression ,
}
2017-10-08 13:51:56 -07:00
#[ derive(Debug, PartialEq, Clone) ]
2017-09-21 16:00:14 -07:00
pub struct Pattern ( Rc < String > ) ;
2017-09-20 21:05:08 -07:00
2017-10-08 13:51:56 -07:00
#[ derive(Debug, PartialEq, Clone) ]
2017-10-02 20:11:27 -07:00
pub struct Operation ( pub Rc < String > ) ;
2017-09-12 02:30:27 -07:00
2017-09-12 05:16:37 -07:00
impl Operation {
fn min_precedence ( ) -> i32 {
i32 ::min_value ( )
}
2017-09-17 05:12:20 -07:00
fn get_precedence ( op : & str ) -> i32 {
2017-09-17 17:44:06 -07:00
match op {
" + " | " - " = > 10 ,
" * " | " / " | " % " = > 20 ,
2017-09-12 02:30:27 -07:00
_ = > 30 ,
}
}
2017-09-17 17:44:06 -07:00
fn is_prefix ( op : & str ) -> bool {
match op {
" + " | " - " | " ! " | " ~ " = > true ,
_ = > false ,
}
}
2017-09-08 16:42:42 -07:00
}
2017-09-15 04:23:39 -07:00
macro_rules ! parse_method {
2017-09-16 13:46:30 -07:00
( $name :ident ( & mut $self :ident ) -> $type :ty $body :block ) = > {
2017-09-15 04:23:39 -07:00
fn $name ( & mut $self ) -> $type {
let next_token = $self . peek ( ) ;
2017-09-17 05:06:58 -07:00
let record = ParseRecord {
production_name : stringify ! ( $name ) . to_string ( ) ,
next_token : format ! ( " {:?} " , next_token ) ,
2018-02-10 15:10:06 -08:00
level : $self . parse_level ,
2017-09-17 05:06:58 -07:00
} ;
2018-02-10 15:10:06 -08:00
$self . parse_level + = 1 ;
2017-09-15 04:23:39 -07:00
$self . parse_record . push ( record ) ;
2018-02-10 15:10:06 -08:00
let result = { $body } ;
if $self . parse_level ! = 0 {
$self . parse_level - = 1 ;
}
result
2017-09-15 04:23:39 -07:00
}
2017-09-16 13:46:30 -07:00
} ;
2017-09-15 04:23:39 -07:00
}
2017-09-28 23:55:10 -07:00
macro_rules ! delimited {
2017-09-30 14:41:37 -07:00
( $self :expr , $start :pat , $start_str :expr , $parse_fn :ident , $( $delim :pat ) | + , $end :pat , $end_str :expr , nonstrict ) = > {
delimited! ( $self , $start , $start_str , $parse_fn , $( $delim ) | * , $end , $end_str , false )
2017-09-30 13:04:56 -07:00
} ;
2017-09-30 14:41:37 -07:00
( $self :expr , $start :pat , $start_str :expr , $parse_fn :ident , $( $delim :pat ) | + , $end :pat , $end_str :expr ) = > {
delimited! ( $self , $start , $start_str , $parse_fn , $( $delim ) | * , $end , $end_str , true )
2017-09-30 13:04:56 -07:00
} ;
2017-09-30 14:41:37 -07:00
( $self :expr , $start :pat , $start_str :expr , $parse_fn :ident , $( $delim :pat ) | + , $end :pat , $end_str :expr , $strictness :expr ) = > {
2017-09-28 23:55:10 -07:00
{
2017-09-30 14:41:37 -07:00
expect! ( $self , $start , $start_str ) ;
2017-09-29 14:10:49 -07:00
let mut acc = vec! [ ] ;
loop {
2017-09-30 13:46:50 -07:00
let peek = $self . peek ( ) ;
match peek {
$end | EOF = > break ,
_ = > ( ) ,
}
if ! $strictness {
match peek {
$( $delim ) | * = > { $self . next ( ) ; continue } ,
_ = > ( )
}
}
2017-09-29 14:10:49 -07:00
acc . push ( $self . $parse_fn ( ) ? ) ;
match $self . peek ( ) {
2017-09-30 13:04:56 -07:00
$( $delim ) | * = > { $self . next ( ) ; continue } ,
2017-09-29 14:10:49 -07:00
_ = > break
} ;
}
2017-09-30 14:41:37 -07:00
expect! ( $self , $end , $end_str ) ;
2017-09-29 14:10:49 -07:00
acc
2017-09-28 23:55:10 -07:00
}
2017-09-30 13:04:56 -07:00
} ;
2017-09-28 23:55:10 -07:00
}
2017-09-11 02:07:17 -07:00
impl Parser {
2017-09-16 13:46:30 -07:00
parse_method! ( program ( & mut self ) -> ParseResult < AST > {
2017-09-15 04:23:39 -07:00
let mut statements = Vec ::new ( ) ;
loop {
match self . peek ( ) {
EOF = > break ,
Newline | Semicolon = > {
self . next ( ) ;
continue ;
} ,
_ = > statements . push ( self . statement ( ) ? ) ,
}
}
Ok ( AST ( statements ) )
} ) ;
2017-09-11 02:07:17 -07:00
2017-09-16 13:46:30 -07:00
parse_method! ( statement ( & mut self ) -> ParseResult < Statement > {
2017-09-11 02:07:17 -07:00
//TODO handle error recovery here
match self . peek ( ) {
Keyword ( Type ) = > self . type_declaration ( ) . map ( | decl | { Statement ::Declaration ( decl ) } ) ,
Keyword ( Func ) = > self . func_declaration ( ) . map ( | func | { Statement ::Declaration ( func ) } ) ,
2017-09-17 06:04:24 -07:00
Keyword ( Var ) | Keyword ( Const ) = > self . binding_declaration ( ) . map ( | decl | Statement ::Declaration ( decl ) ) ,
2017-10-03 03:49:07 -07:00
Keyword ( Trait ) = > self . trait_declaration ( ) . map ( | decl | Statement ::Declaration ( decl ) ) ,
Keyword ( Impl ) = > self . impl_declaration ( ) . map ( | decl | Statement ::Declaration ( decl ) ) ,
2017-09-28 00:06:08 -07:00
_ = > self . expression ( ) . map ( | expr | { Statement ::ExpressionStatement ( expr ) } ) ,
2017-09-11 02:07:17 -07:00
}
2017-09-15 16:40:16 -07:00
} ) ;
2017-09-11 02:07:17 -07:00
2017-10-04 22:02:31 -07:00
parse_method! ( type_declaration ( & mut self ) -> ParseResult < Declaration > {
expect! ( self , Keyword ( Type ) , " 'type' " ) ;
self . type_declaration_body ( )
} ) ;
parse_method! ( type_declaration_body ( & mut self ) -> ParseResult < Declaration > {
if let Keyword ( Alias ) = self . peek ( ) {
self . type_alias ( )
} else {
let name = self . identifier ( ) ? ;
expect! ( self , Operator ( ref c ) if * * c = = " = " , " '=' " ) ;
let body = self . type_body ( ) ? ;
Ok ( Declaration ::TypeDecl ( name , body ) )
}
} ) ;
2017-09-16 14:34:37 -07:00
parse_method! ( type_alias ( & mut self ) -> ParseResult < Declaration > {
2017-09-30 14:41:37 -07:00
expect! ( self , Keyword ( Alias ) , " 'alias' " ) ;
2017-09-13 22:40:05 -07:00
let alias = self . identifier ( ) ? ;
2017-09-30 14:41:37 -07:00
expect! ( self , Operator ( ref c ) if * * c = = " = " , " '=' " ) ;
2017-09-13 22:40:05 -07:00
let original = self . identifier ( ) ? ;
Ok ( Declaration ::TypeAlias ( alias , original ) )
2017-09-16 14:34:37 -07:00
} ) ;
2017-09-13 22:40:05 -07:00
2017-09-16 14:34:37 -07:00
parse_method! ( type_body ( & mut self ) -> ParseResult < TypeBody > {
2017-10-08 18:47:57 -07:00
let mut variants = Vec ::new ( ) ;
variants . push ( self . variant_specifier ( ) ? ) ;
loop {
if let Pipe = self . peek ( ) {
self . next ( ) ;
variants . push ( self . variant_specifier ( ) ? ) ;
} else {
break ;
}
}
Ok ( TypeBody ( variants ) )
} ) ;
parse_method! ( variant_specifier ( & mut self ) -> ParseResult < Variant > {
2017-10-08 19:02:52 -07:00
use self ::Variant ::* ;
let name = self . identifier ( ) ? ;
match self . peek ( ) {
LParen = > {
let tuple_members = delimited! ( self , LParen , '(' , type_name , Comma , RParen , ')' ) ;
Ok ( TupleStruct ( name , tuple_members ) )
} ,
LCurlyBrace = > {
let typed_identifier_list = delimited! ( self , LCurlyBrace , '{' , typed_identifier , Comma , RCurlyBrace , '}' ) ;
Ok ( Record ( name , typed_identifier_list ) )
} ,
2017-10-08 19:15:08 -07:00
_ = > Ok ( UnitStruct ( name ) )
2017-10-08 19:02:52 -07:00
}
} ) ;
2017-10-08 19:30:52 -07:00
parse_method! ( typed_identifier ( & mut self ) -> ParseResult < ( Rc < String > , TypeName ) > {
2017-10-08 19:02:52 -07:00
let identifier = self . identifier ( ) ? ;
expect! ( self , Colon , " ':' " ) ;
let type_name = self . type_name ( ) ? ;
Ok ( ( identifier , type_name ) )
2017-09-16 14:34:37 -07:00
} ) ;
2017-09-11 02:07:17 -07:00
2017-09-16 14:34:37 -07:00
parse_method! ( func_declaration ( & mut self ) -> ParseResult < Declaration > {
2017-10-08 21:21:02 -07:00
let signature = self . signature ( ) ? ;
if let LCurlyBrace = self . peek ( ) {
let statements = delimited! ( self , LCurlyBrace , '{' , statement , Newline | Semicolon , RCurlyBrace , '}' ) ;
Ok ( Declaration ::FuncDecl ( signature , statements ) )
} else {
Ok ( Declaration ::FuncSig ( signature ) )
}
} ) ;
parse_method! ( signature ( & mut self ) -> ParseResult < Signature > {
2017-09-30 14:41:37 -07:00
expect! ( self , Keyword ( Func ) , " 'fn' " ) ;
2017-09-11 20:37:19 -07:00
let name = self . identifier ( ) ? ;
2017-10-08 20:55:05 -07:00
let params = delimited! ( self , LParen , '(' , formal_param , Comma , RParen , ')' ) ;
2017-10-08 21:21:02 -07:00
let type_anno = match self . peek ( ) {
Colon = > Some ( self . type_anno ( ) ? ) ,
_ = > None ,
} ;
Ok ( Signature { name , params , type_anno } )
2017-09-16 14:34:37 -07:00
} ) ;
2017-09-11 20:37:19 -07:00
2017-10-08 20:55:05 -07:00
parse_method! ( formal_param ( & mut self ) -> ParseResult < FormalParam > {
let name = self . identifier ( ) ? ;
let ty = match self . peek ( ) {
Colon = > Some ( self . type_anno ( ) ? ) ,
_ = > None
} ;
Ok ( ( name , ty ) )
2017-09-16 14:34:37 -07:00
} ) ;
2017-09-11 02:07:17 -07:00
2017-09-17 06:04:24 -07:00
parse_method! ( binding_declaration ( & mut self ) -> ParseResult < Declaration > {
let constant = match self . next ( ) {
Keyword ( Var ) = > false ,
Keyword ( Const ) = > true ,
_ = > return ParseError ::new ( " Expected 'var' or 'const' " ) ,
} ;
let name = self . identifier ( ) ? ;
2017-09-30 14:41:37 -07:00
expect! ( self , Operator ( ref o ) if * * o = = " = " , " '=' " ) ;
2017-09-17 06:04:24 -07:00
let expr = self . expression ( ) ? ;
Ok ( Declaration ::Binding { name , constant , expr } )
} ) ;
2017-10-03 03:49:07 -07:00
parse_method! ( trait_declaration ( & mut self ) -> ParseResult < Declaration > {
unimplemented! ( )
} ) ;
parse_method! ( impl_declaration ( & mut self ) -> ParseResult < Declaration > {
expect! ( self , Keyword ( Impl ) , " 'impl' " ) ;
2017-10-08 19:30:52 -07:00
let first = self . type_name ( ) ? ;
2017-10-03 03:49:07 -07:00
let second = if let Keyword ( For ) = self . peek ( ) {
self . next ( ) ;
2017-10-08 19:30:52 -07:00
Some ( self . type_name ( ) ? )
2017-10-03 03:49:07 -07:00
} else {
None
} ;
2017-10-08 14:24:02 -07:00
let block = self . decl_block ( ) ? ;
let result = match ( first , second ) {
2017-10-08 19:30:52 -07:00
( first , Some ( second ) ) = > {
match first {
TypeName ::Singleton { ref name , ref params } if params . len ( ) = = 0 = >
Declaration ::Impl { type_name : second , trait_name : Some ( name . clone ( ) ) , block } ,
_ = > return ParseError ::new ( & format! ( " Invalid name for a trait " ) ) ,
}
} ,
2017-10-08 14:24:02 -07:00
( first , None ) = > Declaration ::Impl { type_name : first , trait_name : None , block }
} ;
Ok ( result )
} ) ;
parse_method! ( decl_block ( & mut self ) -> ParseResult < Vec < Declaration > > {
Ok ( delimited! ( self , LCurlyBrace , '{' , func_declaration , Newline | Semicolon , RCurlyBrace , '}' , nonstrict ) )
2017-10-03 03:49:07 -07:00
} ) ;
2017-09-16 13:46:30 -07:00
parse_method! ( expression ( & mut self ) -> ParseResult < Expression > {
2017-09-27 22:27:50 -07:00
let mut expr_body = self . precedence_expr ( Operation ::min_precedence ( ) ) ? ;
2017-09-26 22:10:13 -07:00
let type_anno = match self . peek ( ) {
2017-09-28 23:55:10 -07:00
Colon = > Some ( self . type_anno ( ) ? ) ,
2017-09-26 22:10:13 -07:00
_ = > None
} ;
2017-10-01 00:50:13 -07:00
if let Some ( _ ) = expr_body . 1 {
2017-09-30 23:30:02 -07:00
return ParseError ::new ( " Bad parse state " ) ;
2017-09-27 22:27:50 -07:00
}
expr_body . 1 = type_anno ;
Ok ( expr_body )
2017-09-26 22:10:13 -07:00
} ) ;
2017-10-08 19:30:52 -07:00
parse_method! ( type_anno ( & mut self ) -> ParseResult < TypeName > {
2017-09-30 14:41:37 -07:00
expect! ( self , Colon , " ':' " ) ;
2017-09-29 14:10:49 -07:00
self . type_name ( )
} ) ;
2017-10-08 19:30:52 -07:00
parse_method! ( type_name ( & mut self ) -> ParseResult < TypeName > {
use self ::TypeName ::* ;
2017-09-28 23:55:10 -07:00
Ok ( match self . peek ( ) {
2017-10-08 19:30:52 -07:00
LParen = > Tuple ( delimited! ( self , LParen , '(' , type_name , Comma , RParen , ')' ) ) ,
_ = > Singleton {
2017-09-30 13:04:56 -07:00
name : self . identifier ( ) ? ,
params : match self . peek ( ) {
2017-09-30 14:41:37 -07:00
LAngleBracket = > delimited! ( self , LAngleBracket , '<' , type_name , Comma , RAngleBracket , '>' ) ,
2017-09-28 23:55:10 -07:00
_ = > vec! [ ] ,
}
}
} )
2017-09-16 13:46:30 -07:00
} ) ;
2017-09-12 05:16:37 -07:00
// this implements Pratt parsing, see http://journal.stuffwithstuff.com/2011/03/19/pratt-parsers-expression-parsing-made-easy/
fn precedence_expr ( & mut self , precedence : i32 ) -> ParseResult < Expression > {
2017-09-17 05:06:58 -07:00
let next_token = self . peek ( ) ;
let record = ParseRecord {
production_name : " precedence_expr " . to_string ( ) ,
next_token : format ! ( " {:?} " , next_token ) ,
2018-02-10 15:10:06 -08:00
level : self . parse_level ,
2017-09-17 05:06:58 -07:00
} ;
2018-02-10 17:45:00 -08:00
self . parse_level + = 1 ;
2017-09-17 05:06:58 -07:00
self . parse_record . push ( record ) ;
2017-09-17 17:44:06 -07:00
let mut lhs = self . prefix_expr ( ) ? ;
2017-09-12 05:16:37 -07:00
loop {
2017-09-17 05:12:20 -07:00
let new_precedence = match self . peek ( ) {
Operator ( op ) = > Operation ::get_precedence ( & * op ) ,
Period = > Operation ::get_precedence ( " . " ) ,
2017-09-12 05:16:37 -07:00
_ = > break ,
} ;
2017-09-17 05:12:20 -07:00
2017-09-12 05:16:37 -07:00
if precedence > = new_precedence {
break ;
}
let op_str = match self . next ( ) {
Operator ( op ) = > op ,
2017-09-17 04:26:44 -07:00
Period = > Rc ::new ( " . " . to_string ( ) ) ,
2017-09-12 05:16:37 -07:00
_ = > unreachable! ( ) ,
} ;
let rhs = self . precedence_expr ( new_precedence ) ? ;
2017-09-17 17:53:21 -07:00
let operation = Operation ( op_str ) ;
2017-09-27 22:27:50 -07:00
lhs = Expression ( ExpressionType ::BinExp ( operation , Box ::new ( lhs ) , Box ::new ( rhs ) ) , None ) ;
2017-09-12 05:16:37 -07:00
}
2018-02-10 17:45:00 -08:00
self . parse_level - = 1 ;
2017-09-12 02:30:27 -07:00
Ok ( lhs )
2017-09-11 02:07:17 -07:00
}
2017-09-17 17:44:06 -07:00
parse_method! ( prefix_expr ( & mut self ) -> ParseResult < Expression > {
match self . peek ( ) {
Operator ( ref op ) if Operation ::is_prefix ( & * op ) = > {
let op_str = match self . next ( ) {
Operator ( op ) = > op ,
_ = > unreachable! ( ) ,
} ;
let expr = self . primary ( ) ? ;
2017-09-27 22:27:50 -07:00
Ok ( Expression (
ExpressionType ::PrefixExp ( Operation ( op_str ) , Box ::new ( expr ) ) ,
None ) )
2017-09-17 17:44:06 -07:00
} ,
_ = > self . primary ( )
}
} ) ;
2017-09-16 14:34:37 -07:00
parse_method! ( primary ( & mut self ) -> ParseResult < Expression > {
2017-09-13 03:46:16 -07:00
match self . peek ( ) {
LParen = > self . paren_expr ( ) ,
2017-09-18 23:22:28 -07:00
Keyword ( Kw ::If ) = > self . if_expr ( ) ,
2017-09-20 20:30:30 -07:00
Keyword ( Kw ::Match ) = > self . match_expr ( ) ,
2017-10-08 22:02:58 -07:00
Keyword ( Kw ::For ) = > self . for_expr ( ) ,
2017-09-13 20:10:06 -07:00
Identifier ( _ ) = > self . identifier_expr ( ) ,
2017-09-13 03:46:16 -07:00
_ = > self . literal ( ) ,
}
2017-09-16 14:34:37 -07:00
} ) ;
2017-09-13 03:46:16 -07:00
2017-09-16 14:34:37 -07:00
parse_method! ( paren_expr ( & mut self ) -> ParseResult < Expression > {
2017-10-06 20:28:07 -07:00
use self ::ExpressionType ::* ;
let mut inner = delimited! ( self , LParen , '(' , expression , Comma , RParen , ')' ) ;
match inner . len ( ) {
0 = > Ok ( Expression ( TupleLiteral ( vec! [ ] ) , None ) ) ,
1 = > Ok ( inner . pop ( ) . unwrap ( ) ) ,
_ = > Ok ( Expression ( TupleLiteral ( inner ) , None ) ) ,
}
2017-09-16 14:34:37 -07:00
} ) ;
2017-09-11 15:42:49 -07:00
2017-09-18 23:22:28 -07:00
parse_method! ( identifier_expr ( & mut self ) -> ParseResult < Expression > {
2017-09-27 22:27:50 -07:00
use self ::ExpressionType ::* ;
2017-09-13 20:10:06 -07:00
let identifier = self . identifier ( ) ? ;
2017-10-08 22:52:05 -07:00
Ok ( match self . peek ( ) {
2017-10-13 18:56:02 -07:00
LCurlyBrace = > {
2017-10-14 13:54:17 -07:00
let fields = self . record_block ( ) ? ;
Expression ( Value ( identifier , fields ) , None )
2017-10-13 18:56:02 -07:00
} ,
2017-09-13 20:10:06 -07:00
LParen = > {
2017-10-08 22:52:05 -07:00
let arguments = self . call_expr ( ) ? ;
2017-10-08 23:02:03 -07:00
//TODO make this be more general
2017-10-14 13:54:17 -07:00
let f = Box ::new ( Expression ( Value ( identifier , vec! [ ] ) , None ) ) ;
2017-10-08 23:02:03 -07:00
Expression ( Call { f , arguments } , None )
2017-09-13 20:10:06 -07:00
} ,
LSquareBracket = > {
2017-09-14 00:11:52 -07:00
let indexers = self . index_expr ( ) ? ;
2017-10-08 22:52:05 -07:00
Expression ( Index {
2017-10-14 13:54:17 -07:00
indexee : Box ::new ( Expression ( Value ( identifier , vec! [ ] ) , None ) ) ,
2017-10-08 22:52:05 -07:00
indexers ,
} , None )
2017-09-14 00:11:52 -07:00
}
2017-10-14 13:54:17 -07:00
_ = > Expression ( Value ( identifier , vec! [ ] ) , None )
2017-10-08 22:52:05 -07:00
} )
2017-09-18 23:22:28 -07:00
} ) ;
2017-09-13 20:10:06 -07:00
2017-10-14 13:54:17 -07:00
parse_method! ( record_block ( & mut self ) -> ParseResult < Vec < ( Rc < String > , Expression ) > > {
Ok ( delimited! ( self , LCurlyBrace , '{' , record_entry , Comma , RCurlyBrace , '}' ) )
} ) ;
parse_method! ( record_entry ( & mut self ) -> ParseResult < ( Rc < String > , Expression ) > {
let field_name = self . identifier ( ) ? ;
expect! ( self , Colon , " : " ) ;
let value = self . expression ( ) ? ;
Ok ( ( field_name , value ) )
} ) ;
2017-09-16 14:34:37 -07:00
parse_method! ( call_expr ( & mut self ) -> ParseResult < Vec < Expression > > {
2017-09-30 14:41:37 -07:00
Ok ( delimited! ( self , LParen , ')' , expression , Comma , RParen , '(' ) )
2017-09-16 14:34:37 -07:00
} ) ;
2017-09-13 20:10:06 -07:00
2017-09-16 14:34:37 -07:00
parse_method! ( index_expr ( & mut self ) -> ParseResult < Vec < Expression > > {
2017-09-30 14:41:37 -07:00
Ok ( delimited! ( self , LSquareBracket , '[' , expression , Comma , RSquareBracket , ']' ) )
2017-09-16 14:34:37 -07:00
} ) ;
2017-09-13 20:10:06 -07:00
2017-09-18 23:22:28 -07:00
parse_method! ( if_expr ( & mut self ) -> ParseResult < Expression > {
2017-09-30 14:41:37 -07:00
expect! ( self , Keyword ( Kw ::If ) , " 'if' " ) ;
2017-09-18 23:22:28 -07:00
let condition = self . expression ( ) ? ;
let then_clause = self . block ( ) ? ;
let else_clause = self . else_clause ( ) ? ;
2017-09-27 22:27:50 -07:00
Ok ( Expression ( ExpressionType ::IfExpression ( Box ::new ( condition ) , then_clause , else_clause ) , None ) )
2017-09-18 23:22:28 -07:00
} ) ;
parse_method! ( else_clause ( & mut self ) -> ParseResult < Option < Vec < Statement > > > {
Ok ( if let Keyword ( Kw ::Else ) = self . peek ( ) {
self . next ( ) ;
Some ( self . block ( ) ? )
} else {
None
} )
} ) ;
parse_method! ( block ( & mut self ) -> ParseResult < Vec < Statement > > {
2017-09-30 14:41:37 -07:00
Ok ( delimited! ( self , LCurlyBrace , '{' , statement , Newline | Semicolon , RCurlyBrace , '}' , nonstrict ) )
2017-09-18 23:22:28 -07:00
} ) ;
2017-09-20 20:30:30 -07:00
parse_method! ( match_expr ( & mut self ) -> ParseResult < Expression > {
2017-09-30 14:41:37 -07:00
expect! ( self , Keyword ( Kw ::Match ) , " 'match' " ) ;
2017-09-20 20:30:30 -07:00
let expr = self . expression ( ) ? ;
2017-09-30 14:11:38 -07:00
//TODO abstract these errors into the delimited macro
//expect!(self, LCurlyBrace, "Expected '{'");
2017-09-20 20:30:30 -07:00
let body = self . match_body ( ) ? ;
2017-09-30 14:11:38 -07:00
//expect!(self, RCurlyBrace, "Expected '}'");
2017-09-27 22:27:50 -07:00
Ok ( Expression ( ExpressionType ::MatchExpression ( Box ::new ( expr ) , body ) , None ) )
2017-09-20 21:05:08 -07:00
} ) ;
parse_method! ( match_body ( & mut self ) -> ParseResult < Vec < MatchArm > > {
2017-09-30 14:41:37 -07:00
Ok ( delimited! ( self , LCurlyBrace , '{' , match_arm , Comma , RCurlyBrace , '}' ) )
2017-09-30 14:11:38 -07:00
} ) ;
parse_method! ( match_arm ( & mut self ) -> ParseResult < MatchArm > {
let pat = self . pattern ( ) ? ;
2017-09-30 14:41:37 -07:00
expect! ( self , Operator ( ref c ) if * * c = = " => " , " '=>' " ) ;
2017-09-30 14:11:38 -07:00
let expr = self . expression ( ) ? ;
Ok ( MatchArm { pat , expr } )
2017-09-21 16:00:14 -07:00
} ) ;
parse_method! ( pattern ( & mut self ) -> ParseResult < Pattern > {
let identifier = self . identifier ( ) ? ;
Ok ( Pattern ( identifier ) )
2017-09-20 20:30:30 -07:00
} ) ;
2017-10-08 22:02:58 -07:00
parse_method! ( for_expr ( & mut self ) -> ParseResult < Expression > {
expect! ( self , Keyword ( Kw ::For ) , " 'for' " ) ;
Ok ( Expression ( ExpressionType ::ForExpression , None ) )
} ) ;
2017-09-16 14:34:37 -07:00
parse_method! ( identifier ( & mut self ) -> ParseResult < Rc < String > > {
2017-09-11 15:42:49 -07:00
match self . next ( ) {
Identifier ( s ) = > Ok ( s ) ,
p = > ParseError ::new ( & format! ( " Expected an identifier, got {:?} " , p ) ) ,
}
2017-09-16 14:34:37 -07:00
} ) ;
2017-09-11 02:07:17 -07:00
2017-09-16 14:34:37 -07:00
parse_method! ( literal ( & mut self ) -> ParseResult < Expression > {
2017-09-27 22:27:50 -07:00
use self ::ExpressionType ::* ;
2017-09-11 02:07:17 -07:00
match self . peek ( ) {
2018-01-08 06:12:45 -08:00
DigitGroup ( _ ) | HexLiteral ( _ ) | BinNumberSigil | Period = > self . number_literal ( ) ,
2017-09-27 22:27:50 -07:00
Keyword ( Kw ::True ) = > {
self . next ( ) ;
Ok ( Expression ( BoolLiteral ( true ) , None ) )
} ,
Keyword ( Kw ::False ) = > {
self . next ( ) ;
Ok ( Expression ( BoolLiteral ( false ) , None ) )
} ,
2017-09-16 15:57:48 -07:00
StrLiteral ( s ) = > {
self . next ( ) ;
2017-09-27 22:27:50 -07:00
Ok ( Expression ( StringLiteral ( s ) , None ) )
2017-09-16 15:57:48 -07:00
}
e = > ParseError ::new ( & format! ( " Expected a literal expression, got {:?} " , e ) ) ,
2017-09-11 02:07:17 -07:00
}
2017-09-16 14:34:37 -07:00
} ) ;
parse_method! ( number_literal ( & mut self ) -> ParseResult < Expression > {
2017-09-11 02:07:17 -07:00
match self . peek ( ) {
2018-01-08 06:12:45 -08:00
HexLiteral ( _ ) | BinNumberSigil = > self . int_literal ( ) ,
2017-09-11 02:07:17 -07:00
_ = > self . float_literal ( ) ,
}
2017-09-16 14:34:37 -07:00
} ) ;
2017-09-11 02:07:17 -07:00
2017-09-16 14:34:37 -07:00
parse_method! ( int_literal ( & mut self ) -> ParseResult < Expression > {
2017-09-27 22:27:50 -07:00
use self ::ExpressionType ::* ;
2017-09-11 02:07:17 -07:00
match self . next ( ) {
BinNumberSigil = > {
2017-09-11 23:27:15 -07:00
let digits = self . digits ( ) ? ;
let n = parse_binary ( digits ) ? ;
2017-09-27 22:27:50 -07:00
Ok ( Expression ( IntLiteral ( n ) , None ) )
2017-09-11 02:07:17 -07:00
} ,
2018-01-08 06:12:45 -08:00
HexLiteral ( text ) = > {
2017-09-16 17:44:06 -07:00
ParseError ::new ( " Not implemented " )
2017-09-11 02:07:17 -07:00
} ,
_ = > return ParseError ::new ( " Expected '0x' or '0b' " ) ,
}
2017-09-16 14:34:37 -07:00
} ) ;
2017-09-11 02:07:17 -07:00
2017-09-16 14:34:37 -07:00
parse_method! ( float_literal ( & mut self ) -> ParseResult < Expression > {
2017-09-27 22:27:50 -07:00
use self ::ExpressionType ::* ;
2017-09-11 02:38:27 -07:00
let mut digits = self . digits ( ) ? ;
if let TokenType ::Period = self . peek ( ) {
self . next ( ) ;
digits . push_str ( " . " ) ;
digits . push_str ( & self . digits ( ) ? ) ;
match digits . parse ::< f64 > ( ) {
2017-09-27 22:27:50 -07:00
Ok ( f ) = > Ok ( Expression ( FloatLiteral ( f ) , None ) ) ,
2017-09-16 17:44:06 -07:00
Err ( e ) = > ParseError ::new ( & format! ( " Float failed to parse with error: {} " , e ) ) ,
2017-09-11 02:38:27 -07:00
}
} else {
match digits . parse ::< u64 > ( ) {
2017-09-27 22:27:50 -07:00
Ok ( d ) = > Ok ( Expression ( IntLiteral ( d ) , None ) ) ,
2017-09-16 17:44:06 -07:00
Err ( e ) = > ParseError ::new ( & format! ( " Integer failed to parse with error: {} " , e ) ) ,
2017-09-11 02:38:27 -07:00
}
2017-09-11 02:07:17 -07:00
}
2017-09-16 14:34:37 -07:00
} ) ;
2017-09-11 02:07:17 -07:00
2017-09-16 14:34:37 -07:00
parse_method! ( digits ( & mut self ) -> ParseResult < String > {
2017-09-11 02:07:17 -07:00
let mut ds = String ::new ( ) ;
loop {
2017-09-11 02:38:27 -07:00
match self . peek ( ) {
Underscore = > { self . next ( ) ; continue ; } ,
DigitGroup ( ref s ) = > { self . next ( ) ; ds . push_str ( s ) } ,
2017-09-11 02:07:48 -07:00
_ = > break ,
2017-09-11 02:07:17 -07:00
}
}
Ok ( ds )
2017-09-16 14:34:37 -07:00
} ) ;
2017-09-11 02:07:17 -07:00
}
2017-09-09 00:31:15 -07:00
2017-09-11 23:27:15 -07:00
fn parse_binary ( digits : String ) -> ParseResult < u64 > {
let mut result : u64 = 0 ;
let mut multiplier = 1 ;
for d in digits . chars ( ) . rev ( ) {
match d {
'1' = > result + = multiplier ,
'0' = > ( ) ,
_ = > return ParseError ::new ( " Encountered a character not '1' or '0 while parsing a binary literal " ) ,
}
multiplier * = 2 ;
}
Ok ( result )
}
2018-01-08 05:57:36 -08:00
fn parse_hex ( digits : String ) -> ParseResult < u64 > {
let mut result : u64 = 0 ;
let mut multiplier : u64 = 1 ;
for d in digits . chars ( ) . rev ( ) {
match d . to_digit ( 16 ) {
Some ( n ) = > result + = n as u64 * multiplier ,
None = > return ParseError ::new ( " Encountered a non-hex digit in a hex literal " ) ,
}
multiplier * = 16 ;
}
Ok ( result )
}
2017-09-16 14:29:22 -07:00
pub fn parse ( input : Vec < Token > ) -> ( Result < AST , ParseError > , Vec < String > ) {
2017-09-09 00:31:15 -07:00
let mut parser = Parser ::new ( input ) ;
2017-09-15 16:35:45 -07:00
let ast = parser . program ( ) ;
2017-09-17 05:06:58 -07:00
let trace = parser . parse_record . into_iter ( ) . map ( | r | {
2018-02-10 15:10:06 -08:00
let mut indent = String ::new ( ) ;
for i in 0 .. r . level {
indent . push ( ' ' ) ;
}
format! ( " {} Production ` {} `, token: {:?} " , indent , r . production_name , r . next_token )
2017-09-17 05:06:58 -07:00
} ) . collect ( ) ;
2017-09-15 16:35:45 -07:00
( ast , trace )
2017-08-29 05:08:09 -07:00
}
2017-09-11 03:21:07 -07:00
#[ cfg(test) ]
mod parse_tests {
2017-09-28 00:06:08 -07:00
use ::std ::rc ::Rc ;
use super ::{ AST , Expression , Statement , Operation , TypeBody , Variant , parse , tokenize } ;
2017-09-11 03:21:07 -07:00
use super ::Statement ::* ;
2017-09-13 22:40:05 -07:00
use super ::Declaration ::* ;
2017-10-08 21:21:02 -07:00
use super ::Signature ;
2017-10-08 19:30:52 -07:00
use super ::TypeName ::* ;
2017-09-28 00:06:08 -07:00
use super ::ExpressionType ::* ;
2017-10-08 19:15:08 -07:00
use super ::Variant ::* ;
2017-09-12 00:48:37 -07:00
2017-09-13 22:40:05 -07:00
macro_rules ! rc {
2017-09-13 22:47:25 -07:00
( $string :tt ) = > { Rc ::new ( stringify! ( $string ) . to_string ( ) ) }
2017-09-13 22:40:05 -07:00
}
2017-09-12 00:48:37 -07:00
macro_rules ! parse_test {
2017-09-16 15:57:48 -07:00
( $string :expr , $correct :expr ) = > { assert_eq! ( parse ( tokenize ( $string ) ) . 0. unwrap ( ) , $correct ) }
2017-09-12 00:48:37 -07:00
}
2017-09-30 13:04:56 -07:00
macro_rules ! parse_error {
( $string :expr ) = > { assert! ( parse ( tokenize ( $string ) ) . 0. is_err ( ) ) }
}
2017-09-12 05:16:37 -07:00
macro_rules ! binexp {
2017-09-28 00:06:08 -07:00
( $op :expr , $lhs :expr , $rhs :expr ) = > { BinExp ( op! ( $op ) , Box ::new ( Expression ( $lhs , None ) ) , Box ::new ( Expression ( $rhs , None ) ) ) }
2017-09-12 05:16:37 -07:00
}
2017-09-17 17:44:06 -07:00
macro_rules ! prefexp {
2017-09-28 00:06:08 -07:00
( $op :expr , $lhs :expr ) = > { PrefixExp ( op! ( $op ) , Box ::new ( Expression ( $lhs , None ) ) ) }
2017-09-17 17:44:06 -07:00
}
2017-09-12 05:16:37 -07:00
macro_rules ! op {
2017-09-17 17:53:21 -07:00
( $op :expr ) = > { Operation ( Rc ::new ( $op . to_string ( ) ) ) }
2017-09-12 05:16:37 -07:00
}
2017-10-10 21:02:32 -07:00
macro_rules ! val {
2017-10-14 13:54:17 -07:00
( $var :expr ) = > { Value ( Rc ::new ( $var . to_string ( ) ) , vec! [ ] ) }
2017-09-13 20:49:17 -07:00
}
2017-09-28 00:06:08 -07:00
macro_rules ! exprstatement {
2017-09-29 19:10:37 -07:00
( $expr_type :expr ) = > { Statement ::ExpressionStatement ( Expression ( $expr_type , None ) ) } ;
( $expr_type :expr , $type_anno :expr ) = > { Statement ::ExpressionStatement ( Expression ( $expr_type , Some ( $type_anno ) ) ) } ;
2017-09-28 00:06:08 -07:00
}
macro_rules ! ex {
( $expr_type :expr ) = > { Expression ( $expr_type , None ) }
}
2017-09-29 19:10:37 -07:00
macro_rules ! ty {
2017-10-08 19:15:08 -07:00
( $name :expr ) = > { Singleton { name : Rc ::new ( $name . to_string ( ) ) , params : vec ! [ ] } } ;
2017-09-29 19:10:37 -07:00
}
2017-09-12 00:48:37 -07:00
2017-09-11 03:21:07 -07:00
#[ test ]
2017-09-13 03:46:16 -07:00
fn parsing_number_literals_and_binexps ( ) {
2017-09-28 00:06:08 -07:00
parse_test! ( " .2 " , AST ( vec! [ exprstatement! ( FloatLiteral ( 0.2 ) ) ] ) ) ;
parse_test! ( " 8.1 " , AST ( vec! [ exprstatement! ( FloatLiteral ( 8.1 ) ) ] ) ) ;
parse_test! ( " 0b010 " , AST ( vec! [ exprstatement! ( IntLiteral ( 2 ) ) ] ) ) ;
2017-09-12 02:33:21 -07:00
parse_test! ( " 3; 4; 4.3 " , AST (
2017-09-28 00:06:08 -07:00
vec! [ exprstatement! ( IntLiteral ( 3 ) ) , exprstatement! ( IntLiteral ( 4 ) ) ,
exprstatement! ( FloatLiteral ( 4.3 ) ) ] ) ) ;
2017-09-12 05:16:37 -07:00
parse_test! ( " 1 + 2 * 3 " , AST ( vec !
[
2017-09-28 00:06:08 -07:00
exprstatement! ( binexp! ( " + " , IntLiteral ( 1 ) , binexp! ( " * " , IntLiteral ( 2 ) , IntLiteral ( 3 ) ) ) )
2017-09-12 05:16:37 -07:00
] ) ) ;
parse_test! ( " 1 * 2 + 3 " , AST ( vec !
[
2017-09-28 00:06:08 -07:00
exprstatement! ( binexp! ( " + " , binexp! ( " * " , IntLiteral ( 1 ) , IntLiteral ( 2 ) ) , IntLiteral ( 3 ) ) )
2017-09-12 05:16:37 -07:00
] ) ) ;
2017-09-12 15:52:23 -07:00
2017-09-28 00:06:08 -07:00
parse_test! ( " 1 && 2 " , AST ( vec! [ exprstatement! ( binexp! ( " && " , IntLiteral ( 1 ) , IntLiteral ( 2 ) ) ) ] ) ) ;
2017-09-12 15:52:23 -07:00
2017-09-28 00:06:08 -07:00
parse_test! ( " 1 + 2 * 3 + 4 " , AST ( vec! [ exprstatement! (
2017-09-28 00:45:36 -07:00
binexp! ( " + " ,
binexp! ( " + " , IntLiteral ( 1 ) , binexp! ( " * " , IntLiteral ( 2 ) , IntLiteral ( 3 ) ) ) ,
IntLiteral ( 4 ) ) ) ] ) ) ;
2017-09-12 15:52:23 -07:00
2017-09-13 03:46:16 -07:00
parse_test! ( " (1 + 2) * 3 " , AST ( vec !
2017-09-28 00:45:36 -07:00
[ exprstatement! ( binexp! ( " * " , binexp! ( " + " , IntLiteral ( 1 ) , IntLiteral ( 2 ) ) , IntLiteral ( 3 ) ) ) ] ) ) ;
2017-09-17 04:26:44 -07:00
2017-09-28 00:06:08 -07:00
parse_test! ( " .1 + .2 " , AST ( vec! [ exprstatement! ( binexp! ( " + " , FloatLiteral ( 0.1 ) , FloatLiteral ( 0.2 ) ) ) ] ) ) ;
2017-09-11 03:21:07 -07:00
}
2017-09-13 03:46:16 -07:00
2017-10-06 20:28:07 -07:00
#[ test ]
fn parsing_tuples ( ) {
parse_test! ( " () " , AST ( vec! [ exprstatement! ( TupleLiteral ( vec! [ ] ) ) ] ) ) ;
parse_test! ( " ( \" hella \" , 34) " , AST ( vec! [ exprstatement! (
TupleLiteral (
vec! [ ex! ( StringLiteral ( rc! ( hella ) ) ) , ex! ( IntLiteral ( 34 ) ) ]
)
) ] ) ) ;
parse_test! ( " ((1+2), \" slough \" ) " , AST ( vec! [ exprstatement! ( TupleLiteral ( vec! [
ex! ( binexp! ( " + " , IntLiteral ( 1 ) , IntLiteral ( 2 ) ) ) ,
ex! ( StringLiteral ( rc! ( slough ) ) ) ,
] ) ) ] ) )
}
2017-09-13 20:49:17 -07:00
#[ test ]
fn parsing_identifiers ( ) {
2017-10-10 21:02:32 -07:00
parse_test! ( " a " , AST ( vec! [ exprstatement! ( val! ( " a " ) ) ] ) ) ;
parse_test! ( " a + b " , AST ( vec! [ exprstatement! ( binexp! ( " + " , val! ( " a " ) , val! ( " b " ) ) ) ] ) ) ;
2017-09-14 00:11:52 -07:00
//parse_test!("a[b]", AST(vec![Expression(
//parse_test!("a[]", <- TODO THIS NEEDS TO FAIL
//parse_test!(damn()[a] ,<- TODO needs to succeed
2017-10-10 21:02:32 -07:00
parse_test! ( " a[b,c] " , AST ( vec! [ exprstatement! ( Index { indexee : Box ::new ( ex! ( val! ( " a " ) ) ) , indexers : vec ! [ ex! ( val! ( " b " ) ) , ex! ( val! ( " c " ) ) ] } ) ] ) ) ;
2017-10-13 18:56:02 -07:00
parse_test! ( " None " , AST ( vec! [ exprstatement! ( val! ( " None " ) ) ] ) ) ;
2017-10-14 13:54:17 -07:00
parse_test! ( " Pandas { a: x + y } " , AST ( vec! [
exprstatement! ( Value ( rc! ( Pandas ) , vec! [ ( rc! ( a ) , ex! ( binexp! ( " + " , val! ( " x " ) , val! ( " y " ) ) ) ) ] ) ) ] ) ) ;
2017-09-13 20:49:17 -07:00
}
2017-09-13 22:40:05 -07:00
2017-09-17 02:38:11 -07:00
#[ test ]
2017-09-17 06:04:24 -07:00
fn parsing_complicated_operators ( ) {
2017-10-10 21:02:32 -07:00
parse_test! ( " a <- b " , AST ( vec! [ exprstatement! ( binexp! ( " <- " , val! ( " a " ) , val! ( " b " ) ) ) ] ) ) ;
parse_test! ( " a || b " , AST ( vec! [ exprstatement! ( binexp! ( " || " , val! ( " a " ) , val! ( " b " ) ) ) ] ) ) ;
parse_test! ( " a<>b " , AST ( vec! [ exprstatement! ( binexp! ( " <> " , val! ( " a " ) , val! ( " b " ) ) ) ] ) ) ;
2017-09-28 00:06:08 -07:00
parse_test! ( " a.b.c.d " , AST ( vec! [ exprstatement! ( binexp! ( " . " ,
2017-09-17 17:57:21 -07:00
binexp! ( " . " ,
2017-10-10 21:02:32 -07:00
binexp! ( " . " , val! ( " a " ) , val! ( " b " ) ) ,
val! ( " c " ) ) ,
val! ( " d " ) ) ) ] ) ) ;
2017-09-28 00:06:08 -07:00
parse_test! ( " -3 " , AST ( vec! [ exprstatement! ( prefexp! ( " - " , IntLiteral ( 3 ) ) ) ] ) ) ;
parse_test! ( " -0.2 " , AST ( vec! [ exprstatement! ( prefexp! ( " - " , FloatLiteral ( 0.2 ) ) ) ] ) ) ;
parse_test! ( " !3 " , AST ( vec! [ exprstatement! ( prefexp! ( " ! " , IntLiteral ( 3 ) ) ) ] ) ) ;
2017-10-10 21:02:32 -07:00
parse_test! ( " a <- -b " , AST ( vec! [ exprstatement! ( binexp! ( " <- " , val! ( " a " ) , prefexp! ( " - " , val! ( " b " ) ) ) ) ] ) ) ;
parse_test! ( " a <--b " , AST ( vec! [ exprstatement! ( binexp! ( " <-- " , val! ( " a " ) , val! ( " b " ) ) ) ] ) ) ;
2017-09-17 02:38:11 -07:00
}
2017-09-14 00:11:52 -07:00
2017-09-13 23:37:49 -07:00
#[ test ]
fn parsing_functions ( ) {
2017-10-08 21:21:02 -07:00
parse_test! ( " fn oi() " , AST ( vec! [ Declaration ( FuncSig ( Signature { name : rc ! ( oi ) , params : vec ! [ ] , type_anno : None } ) ) ] ) ) ;
2017-10-10 21:02:32 -07:00
parse_test! ( " oi() " , AST ( vec! [ exprstatement! ( Call { f : Box ::new ( ex! ( val! ( " oi " ) ) ) , arguments : vec ! [ ] } ) ] ) ) ;
2017-09-28 00:06:08 -07:00
parse_test! ( " oi(a, 2 + 2) " , AST ( vec! [ exprstatement! ( Call
2017-10-10 21:02:32 -07:00
{ f : Box ::new ( ex! ( val! ( " oi " ) ) ) ,
arguments : vec ! [ ex! ( val! ( " a " ) ) , ex! ( binexp! ( " + " , IntLiteral ( 2 ) , IntLiteral ( 2 ) ) ) ]
2017-09-15 03:49:47 -07:00
} ) ] ) ) ;
2017-09-30 13:04:56 -07:00
parse_error! ( " a(b,,c) " ) ;
2017-10-08 20:55:05 -07:00
2017-10-08 21:25:51 -07:00
parse_test! ( " fn a(b, c: Int): Int " , AST ( vec! [ Declaration (
2017-10-08 21:21:02 -07:00
FuncSig ( Signature { name : rc ! ( a ) , params : vec ! [
2017-10-08 20:55:05 -07:00
( rc! ( b ) , None ) , ( rc! ( c ) , Some ( ty! ( " Int " ) ) )
2017-10-08 21:25:51 -07:00
] , type_anno : Some ( ty! ( " Int " ) ) } ) ) ] ) ) ;
parse_test! ( " fn a(x) { x() } " , AST ( vec! [ Declaration (
FuncDecl ( Signature { name : rc ! ( a ) , params : vec ! [ ( rc! ( x ) , None ) ] , type_anno : None } ,
2017-10-10 21:02:32 -07:00
vec! [ exprstatement! ( Call { f : Box ::new ( ex! ( val! ( " x " ) ) ) , arguments : vec ! [ ] } ) ] ) ) ] ) ) ;
2017-09-13 23:37:49 -07:00
}
2017-09-17 04:31:27 -07:00
#[ test ]
2017-09-17 06:04:24 -07:00
fn parsing_bools ( ) {
2017-09-28 00:06:08 -07:00
parse_test! ( " false " , AST ( vec! [ exprstatement! ( BoolLiteral ( false ) ) ] ) ) ;
parse_test! ( " true " , AST ( vec! [ exprstatement! ( BoolLiteral ( true ) ) ] ) ) ;
2017-09-17 04:31:27 -07:00
}
2017-09-16 15:57:48 -07:00
#[ test ]
fn parsing_strings ( ) {
2017-09-28 00:06:08 -07:00
parse_test! ( r # ""hello""# , AST ( vec! [ exprstatement! ( StringLiteral ( rc! ( hello ) ) ) ] ) ) ;
2017-09-16 15:57:48 -07:00
}
2017-09-13 22:40:05 -07:00
#[ test ]
fn parsing_types ( ) {
2017-10-08 19:15:08 -07:00
parse_test! ( " type Yolo = Yolo " , AST ( vec! [ Declaration ( TypeDecl ( rc! ( Yolo ) , TypeBody ( vec! [ UnitStruct ( rc! ( Yolo ) ) ] ) ) ) ] ) ) ;
2017-10-04 22:02:31 -07:00
parse_test! ( " type alias Sex = Drugs " , AST ( vec! [ Declaration ( TypeAlias ( rc! ( Sex ) , rc! ( Drugs ) ) ) ] ) ) ;
2017-10-08 19:15:08 -07:00
parse_test! ( " type Sanchez = Miguel | Alejandro(Int, Option<a>) | Esparanza { a: Int, b: String } " ,
AST ( vec! [ Declaration ( TypeDecl ( rc! ( Sanchez ) , TypeBody ( vec! [
UnitStruct ( rc! ( Miguel ) ) ,
TupleStruct ( rc! ( Alejandro ) , vec! [
Singleton { name : rc ! ( Int ) , params : vec ! [ ] } ,
Singleton { name : rc ! ( Option ) , params : vec ! [ Singleton { name : rc ! ( a ) , params : vec ! [ ] } ] } ,
] ) ,
Record ( rc! ( Esparanza ) , vec! [
( rc! ( a ) , Singleton { name : rc ! ( Int ) , params : vec ! [ ] } ) ,
( rc! ( b ) , Singleton { name : rc ! ( String ) , params : vec ! [ ] } ) ,
] ) ] ) ) ) ] ) ) ;
2017-09-13 22:40:05 -07:00
}
2017-09-17 06:04:24 -07:00
#[ test ]
fn parsing_bindings ( ) {
2017-09-28 00:06:08 -07:00
parse_test! ( " var a = 10 " , AST ( vec! [ Declaration ( Binding { name : rc ! ( a ) , constant : false , expr : ex ! ( IntLiteral ( 10 ) ) } ) ] ) ) ;
parse_test! ( " const a = 2 + 2 " , AST ( vec! [ Declaration ( Binding { name : rc ! ( a ) , constant : true , expr : ex ! ( binexp! ( " + " , IntLiteral ( 2 ) , IntLiteral ( 2 ) ) ) } ) ] ) ) ;
2017-09-17 06:04:24 -07:00
}
2017-09-18 23:22:28 -07:00
#[ test ]
fn parsing_block_expressions ( ) {
2017-09-28 00:06:08 -07:00
parse_test! ( " if a() { b(); c() } " , AST ( vec! [ exprstatement! (
2017-10-10 21:02:32 -07:00
IfExpression ( Box ::new ( ex! ( Call { f : Box ::new ( ex! ( val! ( " a " ) ) ) , arguments : vec ! [ ] } ) ) ,
vec! [ exprstatement! ( Call { f : Box ::new ( ex! ( val! ( " b " ) ) ) , arguments : vec ! [ ] } ) , exprstatement! ( Call { f : Box ::new ( ex! ( val! ( " c " ) ) ) , arguments : vec ! [ ] } ) ] ,
2017-09-28 00:06:08 -07:00
None )
) ] ) ) ;
2017-09-18 23:22:28 -07:00
parse_test! ( r #"
if true {
const a = 10
b
} else {
c
2017-09-28 00:06:08 -07:00
} " #,
AST ( vec! [ exprstatement! ( IfExpression ( Box ::new ( ex! ( BoolLiteral ( true ) ) ) ,
vec! [ Declaration ( Binding { name : rc ! ( a ) , constant : true , expr : ex ! ( IntLiteral ( 10 ) ) } ) ,
2017-10-14 13:54:17 -07:00
exprstatement! ( Value ( rc! ( b ) , vec! [ ] ) ) ] ,
Some ( vec! [ exprstatement! ( Value ( rc! ( c ) , vec! [ ] ) ) ] ) ) ) ] )
2017-09-18 23:22:28 -07:00
) ;
}
2017-09-28 00:45:36 -07:00
2017-10-08 14:24:02 -07:00
#[ test ]
fn parsing_impls ( ) {
parse_test! ( " impl Heh { fn yolo(); fn swagg(); } " , AST ( vec! [
Declaration ( Impl {
2017-10-08 19:39:41 -07:00
type_name : ty ! ( " Heh " ) ,
2017-10-08 14:24:02 -07:00
trait_name : None ,
block : vec ! [
2017-10-08 21:21:02 -07:00
FuncSig ( Signature { name : rc ! ( yolo ) , params : vec ! [ ] , type_anno : None } ) ,
FuncSig ( Signature { name : rc ! ( swagg ) , params : vec ! [ ] , type_anno : None } )
2017-10-08 14:24:02 -07:00
] } ) ] ) ) ;
parse_test! ( " impl Mondai for Lollerino { fn yolo(); fn swagg(); } " , AST ( vec! [
Declaration ( Impl {
2017-10-08 19:39:41 -07:00
type_name : ty ! ( " Lollerino " ) ,
2017-10-08 14:24:02 -07:00
trait_name : Some ( rc! ( Mondai ) ) ,
block : vec ! [
2017-10-08 21:21:02 -07:00
FuncSig ( Signature { name : rc ! ( yolo ) , params : vec ! [ ] , type_anno : None } ) ,
FuncSig ( Signature { name : rc ! ( swagg ) , params : vec ! [ ] , type_anno : None } )
2017-10-08 14:24:02 -07:00
] } ) ] ) ) ;
2017-10-08 19:39:41 -07:00
parse_test! ( " impl Option<WTFMate> { fn oi() } " , AST ( vec! [
Declaration ( Impl {
type_name : Singleton { name : rc ! ( Option ) , params : vec ! [ ty! ( " WTFMate " ) ] } ,
trait_name : None ,
block : vec ! [
2017-10-08 21:21:02 -07:00
FuncSig ( Signature { name : rc ! ( oi ) , params : vec ! [ ] , type_anno : None } ) ,
2017-10-08 19:39:41 -07:00
]
} ) ] ) ) ;
2017-10-08 14:24:02 -07:00
}
2017-09-28 00:45:36 -07:00
#[ test ]
fn parsing_type_annotations ( ) {
parse_test! ( " const a = b : Int " , AST ( vec! [
Declaration ( Binding { name : rc ! ( a ) , constant : true , expr :
2017-10-10 21:02:32 -07:00
Expression ( val! ( " b " ) , Some ( ty! ( " Int " ) ) ) } ) ] ) ) ;
2017-09-28 00:45:36 -07:00
2017-09-29 19:10:37 -07:00
parse_test! ( " a : Int " , AST ( vec! [
2017-10-10 21:02:32 -07:00
exprstatement! ( val! ( " a " ) , ty! ( " Int " ) )
2017-09-29 19:10:37 -07:00
] ) ) ;
parse_test! ( " a : Option<Int> " , AST ( vec! [
2017-10-10 21:02:32 -07:00
exprstatement! ( val! ( " a " ) , Singleton { name : rc ! ( Option ) , params : vec ! [ ty! ( " Int " ) ] } )
2017-09-29 19:10:37 -07:00
] ) ) ;
2017-09-28 00:45:36 -07:00
2017-09-29 19:10:37 -07:00
parse_test! ( " a : KoreanBBQSpecifier<Kimchi, Option<Bulgogi> > " , AST ( vec! [
2017-10-10 21:02:32 -07:00
exprstatement! ( val! ( " a " ) , Singleton { name : rc ! ( KoreanBBQSpecifier ) , params : vec ! [
2017-10-08 19:15:08 -07:00
ty! ( " Kimchi " ) , Singleton { name : rc ! ( Option ) , params : vec ! [ ty! ( " Bulgogi " ) ] }
2017-09-29 19:10:37 -07:00
] } )
] ) ) ;
2017-09-30 01:14:49 -07:00
parse_test! ( " a : (Int, Yolo<a>) " , AST ( vec! [
2017-10-10 21:02:32 -07:00
exprstatement! ( val! ( " a " ) , Tuple (
2017-10-08 19:15:08 -07:00
vec! [ ty! ( " Int " ) , Singleton {
2017-09-30 01:14:49 -07:00
name : rc ! ( Yolo ) , params : vec ! [ ty! ( " a " ) ]
} ] ) ) ] ) ) ;
2017-09-28 00:45:36 -07:00
}
2017-09-11 03:21:07 -07:00
}