2022-12-05 00:38:20 +01:00
use core ::panic ;
2022-12-14 04:12:03 +01:00
use std ::collections ::HashMap ;
2022-11-29 02:04:01 +01:00
use std ::env ;
use std ::fs ;
2022-12-14 07:57:51 +01:00
use std ::iter ::Peekable ;
2022-12-05 00:38:20 +01:00
use std ::process ::exit ;
2022-11-29 02:04:01 +01:00
2022-12-05 00:38:20 +01:00
#[ derive(Debug, Clone, PartialEq) ]
2022-11-29 02:04:01 +01:00
enum Token
{
StringLit ( String , i32 , i32 ) ,
2022-12-14 07:57:51 +01:00
IntLit ( String , i32 , i32 ) ,
2022-12-05 00:38:20 +01:00
Keyword ( String , i32 , i32 ) ,
}
2022-12-14 04:12:03 +01:00
2022-12-05 00:38:20 +01:00
enum TokenizerState
{
Whitespace ,
Quote ,
Keyword ,
Comment ,
}
2022-12-14 07:57:51 +01:00
#[ derive(Debug,Clone,Copy) ]
2022-12-05 00:38:20 +01:00
enum Datatype
{
Int ,
String ,
2022-12-14 07:57:51 +01:00
//Pointer,
2022-12-05 00:38:20 +01:00
Any ,
}
2022-12-14 07:57:51 +01:00
impl PartialEq for Datatype
{
fn eq ( & self , other : & Self ) -> bool
{
core ::mem ::discriminant ( self ) = = core ::mem ::discriminant ( & Datatype ::Any ) | |
core ::mem ::discriminant ( other ) = = core ::mem ::discriminant ( & Datatype ::Any ) | |
core ::mem ::discriminant ( self ) = = core ::mem ::discriminant ( other )
}
}
2022-12-05 00:38:20 +01:00
#[ derive(Debug) ]
struct Function
{
name : String ,
ins : Vec < Datatype > ,
outs : Vec < Datatype > ,
2022-12-14 07:57:51 +01:00
content : Vec < Operation > ,
}
#[ derive(Debug) ]
enum Operation
{
Enqueue ( Datatype , String , i32 , i32 ) ,
Dequeue ( i32 , i32 ) ,
2022-12-14 08:14:27 +01:00
Requeue ( i32 , i32 ) ,
2022-12-14 07:57:51 +01:00
Intrinsic ( String , i32 , i32 ) ,
FunctionCall ( String , i32 , i32 ) ,
If ( Vec < Operation > , Option < Vec < Operation > > , i32 , i32 ) ,
While ( Vec < Operation > , i32 , i32 ) ,
2022-11-29 02:04:01 +01:00
}
fn main ( )
{
2022-12-14 04:12:03 +01:00
let intrinsics : HashMap < & str , ( Vec < Datatype > , Vec < Datatype > ) > = HashMap ::from (
[
( " print " , ( Vec ::from ( [ Datatype ::Any ] ) , Vec ::new ( ) ) ) ,
2022-12-14 07:57:51 +01:00
( " - " , ( Vec ::from ( [ Datatype ::Int , Datatype ::Int ] ) , Vec ::from ( [ Datatype ::Int ] ) ) ) ,
2022-12-14 04:12:03 +01:00
] ) ;
2022-11-29 02:04:01 +01:00
let args : Vec < String > = env ::args ( ) . collect ( ) ;
2022-12-05 00:38:20 +01:00
if args . len ( ) < 2
{
usage ( )
}
2022-12-14 07:57:51 +01:00
let mut debug = false ;
2022-12-14 09:34:41 +01:00
let mut interpret = false ;
2022-12-14 07:57:51 +01:00
for arg in & args [ 3 .. ]
{
match arg . as_str ( )
{
" -d " | " --debug " = > debug = true ,
2022-12-14 09:34:41 +01:00
" -i " | " --interpret " = > interpret = true ,
2022-12-14 07:57:51 +01:00
_ = > panic! ( " Unknown option {} " , arg ) ,
}
}
2022-11-29 02:04:01 +01:00
match args [ 1 ] . as_str ( )
{
" -c " | " --compile " = >
{
let file_content = fs ::read_to_string ( & args [ 2 ] ) . expect ( " Could not read the source file " ) ;
2022-12-05 00:38:20 +01:00
let mut tokens : Vec < Token > = tokenize ( & file_content ) ;
2022-12-14 07:57:51 +01:00
println! ( " ---Done tokenizing, got {} tokens--- " , tokens . len ( ) ) ;
let functions : Vec < Function > = extract_functions ( & mut tokens , & intrinsics , debug ) ;
println! ( " ---Done extracting functions, got {} functions and reduced the token count to {} --- " , functions . len ( ) , tokens . len ( ) ) ;
let operations = parse_until_delimiter ( & mut tokens . iter ( ) . peekable ( ) , & intrinsics , None , debug ) ;
println! ( " ---Done parsing tokens into {} operations--- " , operations . len ( ) ) ;
validate_function_calls ( & operations , & functions , debug ) ;
println! ( " ---Done validating function calls--- " ) ;
typecheck ( & operations , & functions , & intrinsics , debug ) ;
println! ( " ---Done typechecking--- " ) ;
2022-12-14 09:34:41 +01:00
if interpret
{
println! ( " ---Starting to interpret the program--- \n \n " ) ;
interpret_program ( & operations , & mut Vec ::new ( ) , & functions , & intrinsics , debug ) ;
}
2022-11-29 02:04:01 +01:00
}
2022-12-05 00:38:20 +01:00
_ = > panic! ( " Unknown option {} " , args [ 1 ] )
2022-11-29 02:04:01 +01:00
}
}
2022-12-14 09:34:41 +01:00
fn interpret_program ( operations : & Vec < Operation > , queue : & mut Vec < String > , functions : & Vec < Function > , intrinsics : & HashMap < & str , ( Vec < Datatype > , Vec < Datatype > ) > , debug : bool )
{
for operation in operations
{
if debug
{
println! ( " before: {:?} : {:?} " , operation , queue ) ;
}
match operation
{
Operation ::Dequeue ( _ , _ ) = >
{
queue . remove ( 0 ) ;
}
Operation ::Enqueue ( _ , value , _ , _ ) = >
{
queue . push ( value . clone ( ) ) ;
}
Operation ::Requeue ( _ , _ ) = >
{
let val = queue . remove ( 0 ) ;
queue . push ( val ) ;
}
Operation ::FunctionCall ( function_name , _ , _ ) = >
{
interpret_program ( & functions . iter ( ) . find ( | x | & x . name = = function_name ) . unwrap ( ) . content , queue , functions , intrinsics , debug ) ;
}
Operation ::If ( if_block , maybe_else_block , _ , _ ) = >
{
let val = queue . remove ( 0 ) ;
// TODO: Add bool type
if val = = " 0 "
{
interpret_program ( if_block , queue , functions , intrinsics , debug ) ;
}
else if let Some ( else_block ) = maybe_else_block
{
interpret_program ( else_block , queue , functions , intrinsics , debug ) ;
}
}
Operation ::Intrinsic ( intrinsic_name , line , col ) = >
{
match intrinsic_name . as_str ( )
{
" print " = >
{
print! ( " {} " , queue . remove ( 0 ) ) ;
}
" - " = >
{
let minuend = queue . remove ( 0 ) . parse ::< i64 > ( ) . unwrap ( ) ;
let subtrahend = queue . remove ( 0 ) . parse ::< i64 > ( ) . unwrap ( ) ;
queue . push ( ( minuend - subtrahend ) . to_string ( ) ) ;
}
_ = >
{
panic! ( " Unexpected intrinsic ' {} ' at {} : {} " , intrinsic_name , line , col ) ;
}
}
}
Operation ::While ( while_block , _ , _ ) = >
{
loop
{
let val = queue . get ( 0 ) . unwrap ( ) ;
if val = = " 0 "
{
break ;
}
interpret_program ( while_block , queue , functions , intrinsics , debug ) ;
}
}
}
if debug
{
println! ( " after: {:?} : {:?} " , operation , queue ) ;
}
}
}
2022-12-14 07:57:51 +01:00
fn typecheck ( operations : & Vec < Operation > , functions : & Vec < Function > , intrinsics : & HashMap < & str , ( Vec < Datatype > , Vec < Datatype > ) > , debug : bool )
2022-12-14 04:12:03 +01:00
{
for function in functions
{
2022-12-14 07:57:51 +01:00
if debug
{
println! ( " Now typechecking function ' {} ' " , function . name ) ;
}
typecheck_block ( & function . content , & function . ins , & function . outs , functions , intrinsics , debug ) ;
if debug
{
println! ( " Successfully typechecked function ' {} ' " , function . name ) ;
}
2022-12-14 04:12:03 +01:00
}
2022-12-14 07:57:51 +01:00
if debug
2022-12-14 04:12:03 +01:00
{
2022-12-14 07:57:51 +01:00
println! ( " Now typechecking main operations " ) ;
}
typecheck_block ( operations , & Vec ::new ( ) , & Vec ::new ( ) , functions , intrinsics , debug ) ;
if debug
{
println! ( " Successfully typechecked main operations " ) ;
2022-12-14 04:12:03 +01:00
}
}
2022-12-14 07:57:51 +01:00
fn typecheck_block ( operations : & Vec < Operation > , ins : & Vec < Datatype > , outs : & Vec < Datatype > , functions : & Vec < Function > , intrinsics : & HashMap < & str , ( Vec < Datatype > , Vec < Datatype > ) > , debug : bool )
2022-12-14 04:12:03 +01:00
{
2022-12-14 07:57:51 +01:00
let actual_outs = get_return_type ( operations , ins , functions , intrinsics , debug ) ;
if & actual_outs ! = outs
2022-12-14 04:12:03 +01:00
{
2022-12-14 07:57:51 +01:00
let ( line , col ) = match operations . last ( )
2022-12-14 04:12:03 +01:00
{
2022-12-14 07:57:51 +01:00
Some ( operation ) = >
2022-12-14 04:12:03 +01:00
{
2022-12-14 07:57:51 +01:00
match operation
2022-12-14 04:12:03 +01:00
{
2022-12-14 07:57:51 +01:00
Operation ::Enqueue ( _ , _ , line , col ) |
2022-12-14 08:14:27 +01:00
Operation ::Requeue ( line , col ) |
2022-12-14 07:57:51 +01:00
Operation ::FunctionCall ( _ , line , col ) |
Operation ::If ( _ , _ , line , col ) |
Operation ::Intrinsic ( _ , line , col ) |
Operation ::While ( _ , line , col ) |
Operation ::Dequeue ( line , col ) = > ( * line , * col ) ,
2022-12-14 04:12:03 +01:00
}
}
2022-12-14 07:57:51 +01:00
None = > ( - 1 , - 1 )
} ;
panic! ( " Wrong queue state at the end of a block, expected {:?} but got {:?} at {} : {} " , outs , actual_outs , line , col ) ;
2022-12-14 04:12:03 +01:00
}
}
2022-12-14 07:57:51 +01:00
fn get_return_type ( operations : & Vec < Operation > , ins : & Vec < Datatype > , functions : & Vec < Function > , intrinsics : & HashMap < & str , ( Vec < Datatype > , Vec < Datatype > ) > , debug : bool ) -> Vec < Datatype >
2022-12-14 04:12:03 +01:00
{
2022-12-14 07:57:51 +01:00
let type_queue : & mut Vec < Datatype > = & mut Vec ::new ( ) ;
2022-12-14 04:12:03 +01:00
type_queue . extend_from_slice ( ins ) ;
2022-12-14 07:57:51 +01:00
let mut debug_string = String ::from ( " " ) ;
for operation in operations
2022-12-14 04:12:03 +01:00
{
2022-12-14 07:57:51 +01:00
if debug
{
debug_string = format! ( " operation: {:?} : {:?} " , operation , type_queue ) ;
}
match operation
2022-12-14 04:12:03 +01:00
{
2022-12-14 07:57:51 +01:00
Operation ::Dequeue ( line , col ) = >
2022-12-14 04:12:03 +01:00
{
2022-12-14 07:57:51 +01:00
if type_queue . is_empty ( )
2022-12-14 04:12:03 +01:00
{
2022-12-14 07:57:51 +01:00
panic! ( " Attempted to dequeue an element while the queue was empty at {} : {} " , line , col ) ;
}
type_queue . remove ( 0 ) ;
}
Operation ::Enqueue ( datatype , _ , _ , _ ) = >
{
type_queue . push ( * datatype ) ;
}
2022-12-14 08:14:27 +01:00
Operation ::Requeue ( line , col ) = >
{
if type_queue . is_empty ( )
{
panic! ( " Attempted to requeue an element while the queue was empty at {} : {} " , line , col ) ;
}
let typ = type_queue . remove ( 0 ) ;
type_queue . push ( typ ) ;
}
2022-12-14 07:57:51 +01:00
Operation ::FunctionCall ( function_name , line , col ) = >
{
let function = functions . iter ( ) . find ( | x | & x . name = = function_name ) . unwrap ( ) ;
if function . ins . len ( ) > type_queue . len ( )
{
panic! ( " Attempted to call function ' {} ' at {} : {} , with insufficient elements in the queue, expected {:?} but got {:?} " , function . name , line , col , function . ins , type_queue ) ;
2022-12-14 04:12:03 +01:00
}
2022-12-14 07:57:51 +01:00
for in_type in & function . ins
2022-12-14 04:12:03 +01:00
{
2022-12-14 07:57:51 +01:00
let actual_type = type_queue . remove ( 0 ) ;
if in_type ! = & actual_type
2022-12-14 04:12:03 +01:00
{
2022-12-14 07:57:51 +01:00
panic! ( " Attempted to call function ' {} ' at {} : {} with a wrong parameter, expected {:?} but got {:?} " , function . name , line , col , in_type , actual_type ) ;
2022-12-14 04:12:03 +01:00
}
2022-12-14 07:57:51 +01:00
}
type_queue . extend_from_slice ( & function . outs ) ;
}
Operation ::If ( if_block , maybe_else_block , line , col ) = >
{
if type_queue . is_empty ( )
{
panic! ( " Encountered if block with an empty queue at {} : {} " , line , col ) ;
}
let comparison_type = type_queue . remove ( 0 ) ;
if comparison_type ! = Datatype ::Int
{
panic! ( " Expected an int as an if condition but got {:?} instead at {} : {} " , comparison_type , line , col ) ;
}
if debug
{
println! ( " Starting to typecheck if block " ) ;
}
let if_ret = get_return_type ( if_block , & type_queue , functions , intrinsics , debug ) ;
let else_ret =
if let Some ( else_block ) = maybe_else_block
{
if debug
2022-12-14 04:12:03 +01:00
{
2022-12-14 07:57:51 +01:00
println! ( " Starting to typecheck else block " ) ;
2022-12-14 04:12:03 +01:00
}
2022-12-14 07:57:51 +01:00
get_return_type ( else_block , & type_queue , functions , intrinsics , debug )
2022-12-14 04:12:03 +01:00
}
2022-12-14 07:57:51 +01:00
else
{
type_queue . clone ( )
} ;
if if_ret ! = else_ret
{
panic! ( " Incompatible queue states after if/else construction, expected {:?} but got {:?} " , if_ret , else_ret ) ;
}
type_queue . clear ( ) ;
type_queue . extend_from_slice ( & if_ret ) ;
}
Operation ::Intrinsic ( intrinsic_name , line , col ) = >
{
let io = intrinsics . get ( intrinsic_name . as_str ( ) ) . unwrap ( ) ;
if io . 0. len ( ) > type_queue . len ( )
2022-12-14 04:12:03 +01:00
{
2022-12-14 07:57:51 +01:00
panic! ( " Attempted to call intrinsic ' {} ' at {} : {} , with insufficient elements in the queue, expected {:?} but got {:?} " , intrinsic_name , line , col , io . 0 , type_queue ) ;
}
for in_type in & io . 0
{
let actual_type = type_queue . remove ( 0 ) ;
if in_type ! = & actual_type
2022-12-14 04:12:03 +01:00
{
2022-12-14 07:57:51 +01:00
panic! ( " Attempted to call intrinsic ' {} ' at {} : {} with a wrong parameter, expected {:?} but got {:?} " , intrinsic_name , line , col , in_type , actual_type ) ;
2022-12-14 04:12:03 +01:00
}
}
2022-12-14 07:57:51 +01:00
type_queue . extend_from_slice ( & io . 1 ) ;
}
Operation ::While ( while_block , line , col ) = >
{
if type_queue . is_empty ( )
{
panic! ( " Encountered while block with an empty queue at {} : {} " , line , col ) ;
}
let & comparison_type = type_queue . get ( 0 ) . unwrap ( ) ;
if comparison_type ! = Datatype ::Int
{
panic! ( " Expected an int as a while condition but got {:?} instead at {} : {} " , comparison_type , line , col ) ;
}
if debug
2022-12-14 04:12:03 +01:00
{
2022-12-14 07:57:51 +01:00
println! ( " Starting to typecheck while block " ) ;
2022-12-14 04:12:03 +01:00
}
2022-12-14 07:57:51 +01:00
typecheck_block ( while_block , type_queue , type_queue , functions , intrinsics , debug ) ;
2022-12-14 04:12:03 +01:00
}
}
2022-12-14 07:57:51 +01:00
if debug
{
println! ( " {} => {:?} " , debug_string , type_queue ) ;
}
2022-12-14 04:12:03 +01:00
}
2022-12-14 07:57:51 +01:00
return type_queue . clone ( ) ;
2022-12-14 04:12:03 +01:00
}
2022-12-14 07:57:51 +01:00
fn validate_function_calls ( operations : & Vec < Operation > , functions : & Vec < Function > , debug : bool )
2022-12-05 00:38:20 +01:00
{
2022-12-14 07:57:51 +01:00
for function in functions
2022-12-05 00:38:20 +01:00
{
2022-12-14 07:57:51 +01:00
validate_function_calls_in_block ( & function . content , functions , debug ) ;
if debug
2022-12-05 00:38:20 +01:00
{
2022-12-14 07:57:51 +01:00
println! ( " Successfully validated function calls in function ' {} ' " , function . name ) ;
}
}
validate_function_calls_in_block ( operations , functions , debug ) ;
if debug
{
println! ( " Successfully validated function calls in main operations " ) ;
}
}
fn validate_function_calls_in_block ( block : & Vec < Operation > , functions : & Vec < Function > , debug : bool )
{
for operation in block
{
match operation
{
2022-12-14 08:14:27 +01:00
Operation ::Intrinsic ( _ , _ , _ ) | Operation ::Enqueue ( _ , _ , _ , _ ) | Operation ::Dequeue ( _ , _ ) | Operation ::Requeue ( _ , _ ) = > { } ,
2022-12-14 07:57:51 +01:00
Operation ::FunctionCall ( function_name , line , col ) = >
2022-12-05 00:38:20 +01:00
{
2022-12-14 07:57:51 +01:00
if ! functions . iter ( ) . any ( | x | & x . name = = function_name )
2022-12-05 00:38:20 +01:00
{
2022-12-14 07:57:51 +01:00
panic! ( " Call to unknown function {} at {} : {} " , function_name , line , col ) ;
2022-12-05 00:38:20 +01:00
}
}
2022-12-14 07:57:51 +01:00
Operation ::If ( if_block , maybe_else_block , _ , _ ) = >
2022-12-05 00:38:20 +01:00
{
2022-12-14 07:57:51 +01:00
validate_function_calls_in_block ( if_block , functions , debug ) ;
if let Some ( else_block ) = maybe_else_block
2022-12-05 00:38:20 +01:00
{
2022-12-14 07:57:51 +01:00
validate_function_calls_in_block ( else_block , functions , debug ) ;
2022-12-05 00:38:20 +01:00
}
}
2022-12-14 07:57:51 +01:00
Operation ::While ( while_block , _ , _ ) = >
2022-12-05 00:38:20 +01:00
{
2022-12-14 07:57:51 +01:00
validate_function_calls_in_block ( while_block , functions , debug ) ;
}
}
}
}
fn extract_functions ( tokens : & mut Vec < Token > , intrinsics : & HashMap < & str , ( Vec < Datatype > , Vec < Datatype > ) > , debug : bool ) -> Vec < Function >
{
let mut tokens_iter = tokens . iter ( ) . peekable ( ) ;
let mut functions : Vec < Function > = Vec ::new ( ) ;
let mut new_tokens : Vec < Token > = Vec ::new ( ) ;
while let Some ( token ) = tokens_iter . next ( )
{
if let Token ::Keyword ( word , line , col ) = token
{
if word = = " function "
{
if debug
2022-12-05 00:38:20 +01:00
{
2022-12-14 07:57:51 +01:00
print! ( " Found a function at {} : {} " , line , col ) ;
}
let mut ins : Vec < Datatype > = Vec ::new ( ) ;
loop
{
let maybe_token = tokens_iter . next ( ) ;
match maybe_token
2022-12-05 00:38:20 +01:00
{
2022-12-14 07:57:51 +01:00
Some ( token ) = >
2022-12-05 00:38:20 +01:00
{
2022-12-14 07:57:51 +01:00
match token
2022-12-05 00:38:20 +01:00
{
2022-12-14 07:57:51 +01:00
Token ::IntLit ( _ , line , col ) | Token ::StringLit ( _ , line , col ) = >
{
panic! ( " Expected input parameters for a function but got {:?} instead at {} : {} " , token , line , col ) ;
}
Token ::Keyword ( word , line , col ) = >
2022-12-05 00:38:20 +01:00
{
2022-12-14 07:57:51 +01:00
if word = = " => "
2022-12-05 00:38:20 +01:00
{
2022-12-14 07:57:51 +01:00
break ;
2022-12-05 00:38:20 +01:00
}
2022-12-14 07:57:51 +01:00
match word . as_str ( )
2022-12-14 04:12:03 +01:00
{
2022-12-14 07:57:51 +01:00
" any " = > ins . push ( Datatype ::Any ) ,
" str " = > ins . push ( Datatype ::String ) ,
" int " = > ins . push ( Datatype ::Int ) ,
_ = > panic! ( " Expected input parameters for a function but got {} instead at {} : {} " , word , line , col )
2022-12-14 04:12:03 +01:00
}
2022-12-05 00:38:20 +01:00
}
}
}
2022-12-14 07:57:51 +01:00
None = > panic! ( " Unexpected end of file while extracting a function " )
2022-12-05 00:38:20 +01:00
}
}
2022-12-14 07:57:51 +01:00
if debug
2022-12-05 00:38:20 +01:00
{
2022-12-14 07:57:51 +01:00
println! ( " ins: {:?} " , ins ) ;
2022-12-05 00:38:20 +01:00
}
2022-12-14 07:57:51 +01:00
let mut outs : Vec < Datatype > = Vec ::new ( ) ;
loop
2022-12-05 00:38:20 +01:00
{
2022-12-14 07:57:51 +01:00
let maybe_token = tokens_iter . next ( ) ;
match maybe_token
2022-12-05 00:38:20 +01:00
{
2022-12-14 07:57:51 +01:00
Some ( token ) = >
2022-12-14 04:12:03 +01:00
{
2022-12-14 07:57:51 +01:00
match token
2022-12-14 04:12:03 +01:00
{
2022-12-14 07:57:51 +01:00
Token ::IntLit ( _ , line , col ) | Token ::StringLit ( _ , line , col ) = >
{
panic! ( " Expected input parameters for a function but got {:?} instead at {} : {} " , token , line , col ) ;
}
Token ::Keyword ( word , line , col ) = >
{
match word . as_str ( )
{
" any " = > outs . push ( Datatype ::Any ) ,
" str " = > outs . push ( Datatype ::String ) ,
" int " = > outs . push ( Datatype ::Int ) ,
2022-12-14 09:34:41 +01:00
" { " | " } " | " deq " | " req " = > panic! ( " Expected function name but got {} at {} : {} " , word , line , col ) ,
2022-12-14 07:57:51 +01:00
_ = >
{
if functions . iter ( ) . any ( | x | & x . name = = word )
{
panic! ( " Redeclaration of function ' {} ' at {} : {} " , word , line , col ) ;
}
2022-12-14 09:34:41 +01:00
if intrinsics . contains_key ( word . as_str ( ) )
{
panic! ( " Function name {} at {} : {} is already an intrinsic " , word , line , col ) ;
}
2022-12-14 07:57:51 +01:00
if debug
{
println! ( " outs: {:?} " , outs ) ;
}
let block = parse_block ( & mut tokens_iter , intrinsics , debug ) ;
functions . push ( Function { name : word . clone ( ) , ins , outs , content : block } ) ;
break ;
}
}
}
2022-12-14 04:12:03 +01:00
}
}
2022-12-14 07:57:51 +01:00
None = > panic! ( " Unexpected end of file while extracting a function " )
2022-12-05 00:38:20 +01:00
}
}
}
2022-12-14 07:57:51 +01:00
else
{
new_tokens . push ( token . clone ( ) ) ;
}
}
else
{
new_tokens . push ( token . clone ( ) ) ;
2022-12-05 00:38:20 +01:00
}
2022-12-14 07:57:51 +01:00
}
tokens . clear ( ) ;
tokens . extend_from_slice ( & new_tokens ) ;
return functions ;
}
2022-12-05 00:38:20 +01:00
2022-12-14 07:57:51 +01:00
fn parse_block ( tokens_iter : & mut Peekable < std ::slice ::Iter < Token > > , intrinsics : & HashMap < & str , ( Vec < Datatype > , Vec < Datatype > ) > , debug : bool ) -> Vec < Operation >
{
if let Some ( Token ::Keyword ( word , line , col ) ) = tokens_iter . next ( )
{
if word ! = " { "
2022-12-05 00:38:20 +01:00
{
2022-12-14 07:57:51 +01:00
panic! ( " Expected ' {{ ' to open a block but got {} at {} : {} " , word , line , col ) ;
2022-12-05 00:38:20 +01:00
}
}
2022-12-14 07:57:51 +01:00
else
2022-12-05 00:38:20 +01:00
{
2022-12-14 07:57:51 +01:00
panic! ( " Expected ' {{ ' to open a block " ) ;
2022-12-05 00:38:20 +01:00
}
2022-12-14 07:57:51 +01:00
return parse_until_delimiter ( tokens_iter , intrinsics , Some ( " } " ) , debug ) ;
2022-12-05 00:38:20 +01:00
}
2022-12-14 07:57:51 +01:00
fn parse_until_delimiter ( tokens_iter : & mut Peekable < std ::slice ::Iter < Token > > , intrinsics : & HashMap < & str , ( Vec < Datatype > , Vec < Datatype > ) > , delimiter : Option < & str > , debug : bool ) -> Vec < Operation >
2022-12-05 00:38:20 +01:00
{
2022-12-14 07:57:51 +01:00
let mut operations : Vec < Operation > = Vec ::new ( ) ;
loop
{
let maybe_token = tokens_iter . next ( ) ;
match maybe_token
{
Some ( token ) = >
{
match token
{
Token ::IntLit ( value , line , col ) = >
{
operations . push ( Operation ::Enqueue ( Datatype ::Int , value . clone ( ) , * line , * col ) ) ;
}
Token ::StringLit ( value , line , col ) = >
{
operations . push ( Operation ::Enqueue ( Datatype ::String , value . clone ( ) , * line , * col ) ) ;
}
Token ::Keyword ( word , line , col ) = >
{
if intrinsics . contains_key ( word . as_str ( ) )
{
operations . push ( Operation ::Intrinsic ( word . clone ( ) , * line , * col ) ) ;
}
else if word = = " if "
{
let block = parse_block ( tokens_iter , intrinsics , debug ) ;
let else_block =
if let Some ( Token ::Keyword ( maybe_else , _ , _ ) ) = tokens_iter . peek ( )
{
if maybe_else = = " else "
{
tokens_iter . next ( ) ;
Some ( parse_block ( tokens_iter , intrinsics , debug ) )
}
else
{
None
}
}
else
{
None
} ;
operations . push ( Operation ::If ( block , else_block , * line , * col ) ) ;
}
else if word = = " while "
{
operations . push ( Operation ::While ( parse_block ( tokens_iter , intrinsics , debug ) , * line , * col ) ) ;
}
else if word = = " deq "
{
operations . push ( Operation ::Dequeue ( * line , * col ) ) ;
}
2022-12-14 08:14:27 +01:00
else if word = = " req "
{
operations . push ( Operation ::Requeue ( * line , * col ) ) ;
}
2022-12-14 07:57:51 +01:00
else if Some ( word . as_str ( ) ) = = delimiter
{
return operations ;
}
else if word = = " { " | | word = = " function "
{
panic! ( " Unexpected keyword {} at {} : {} " , word , line , col ) ;
}
else
{
operations . push ( Operation ::FunctionCall ( word . clone ( ) , * line , * col ) ) ;
}
}
}
}
None = >
{
if delimiter . is_some ( )
{
panic! ( " Reached the end of the file while parsing a block " )
}
else
{
return operations ;
}
}
}
}
2022-12-05 00:38:20 +01:00
}
fn usage ( )
{
println! ( " Usage: kurz -c path/to/file " ) ;
exit ( 0 ) ;
}
2022-11-29 02:04:01 +01:00
fn tokenize ( text : & str ) -> Vec < Token >
{
let mut tokens : Vec < Token > = Vec ::new ( ) ;
let mut line = 1 ;
let mut col = 1 ;
let mut state = TokenizerState ::Whitespace ;
let mut word = String ::new ( ) ;
2022-12-05 00:38:20 +01:00
let mut iter = text . chars ( ) . peekable ( ) ;
while let Some ( ch ) = iter . next ( )
2022-11-29 02:04:01 +01:00
{
2022-12-05 00:38:20 +01:00
if ch = = '/' & & iter . peek ( ) = = Some ( & '/' )
{
state = TokenizerState ::Comment ;
}
2022-11-29 02:04:01 +01:00
match state
{
2022-12-05 00:38:20 +01:00
TokenizerState ::Comment = >
{
if ch = = '\n'
{
state = TokenizerState ::Whitespace ;
}
}
2022-11-29 02:04:01 +01:00
TokenizerState ::Whitespace = >
{
// If ch is whitespace, do nothing
if ! ch . is_whitespace ( )
{
match ch
{
'"' = >
{
state = TokenizerState ::Quote ;
}
_ = >
{
2022-12-05 00:38:20 +01:00
state = TokenizerState ::Keyword ;
2022-11-29 02:04:01 +01:00
word . push ( ch ) ;
}
}
}
}
TokenizerState ::Quote = >
{
if ch = = '"'
{
state = TokenizerState ::Whitespace ;
tokens . push ( Token ::StringLit ( word . clone ( ) , line , col ) ) ;
word . clear ( ) ;
}
else
{
word . push ( ch ) ;
}
}
2022-12-05 00:38:20 +01:00
TokenizerState ::Keyword = >
2022-11-29 02:04:01 +01:00
{
if ch . is_whitespace ( )
{
state = TokenizerState ::Whitespace ;
2022-12-14 07:57:51 +01:00
if let Ok ( _ ) = word . parse ::< i64 > ( )
2022-12-05 00:38:20 +01:00
{
2022-12-14 07:57:51 +01:00
tokens . push ( Token ::IntLit ( word . clone ( ) , line , col ) ) ;
2022-12-05 00:38:20 +01:00
}
else
2022-11-29 02:04:01 +01:00
{
2022-12-05 00:38:20 +01:00
tokens . push ( Token ::Keyword ( word . clone ( ) , line , col ) ) ;
}
word . clear ( ) ;
2022-11-29 02:04:01 +01:00
}
else
{
match ch
{
'"' = > panic! ( " Having ' \" ' in the middle of a word is not allowed " ) ,
_ = >
{
word . push ( ch ) ;
}
}
}
}
}
col + = 1 ;
if ch = = '\n'
{
col = 1 ;
line + = 1 ;
}
}
match state
{
TokenizerState ::Quote = >
{
panic! ( " Encountered EOF before closing string " ) ;
}
2022-12-05 00:38:20 +01:00
TokenizerState ::Whitespace | TokenizerState ::Comment = > { } ,
TokenizerState ::Keyword = >
2022-11-29 02:04:01 +01:00
{
2022-12-05 00:38:20 +01:00
tokens . push ( Token ::Keyword ( word . clone ( ) , line , col ) ) ;
2022-11-29 02:04:01 +01:00
}
}
tokens
}