λ Support functions! #5
@@ -30,11 +30,15 @@ extern {
|
||||
enum Token {
|
||||
"=" => Token::Equals,
|
||||
";" => Token::Semi,
|
||||
"," => Token::Comma,
|
||||
"(" => Token::LeftParen,
|
||||
")" => Token::RightParen,
|
||||
"<" => Token::LessThan,
|
||||
">" => Token::GreaterThan,
|
||||
"{" => Token::OpenBrace,
|
||||
"}" => Token::CloseBrace,
|
||||
|
||||
"function" => Token::Function,
|
||||
"print" => Token::Print,
|
||||
|
||||
"+" => Token::Operator('+'),
|
||||
@@ -53,11 +57,43 @@ extern {
|
||||
|
||||
pub Program: Program = {
|
||||
// a program is just a set of statements
|
||||
<stmts:Statements> => Program {
|
||||
<stmts:ProgramTopLevel> => Program {
|
||||
statements: stmts
|
||||
}
|
||||
}
|
||||
|
||||
ProgramTopLevel: Vec<Statement> = {
|
||||
<rest: ProgramTopLevel> Function => unimplemented!(),
|
||||
<mut rest: ProgramTopLevel> <next:Statement> => {
|
||||
rest.push(next);
|
||||
rest
|
||||
},
|
||||
=> Vec::new(),
|
||||
}
|
||||
|
||||
Function: () = {
|
||||
"function" "(" Arguments OptionalComma ")" Expression => unimplemented!(),
|
||||
}
|
||||
|
||||
Arguments: Vec<Name> = {
|
||||
<mut args:Arguments> <arg:Argument> => {
|
||||
args.push(arg);
|
||||
args
|
||||
},
|
||||
|
||||
=> Vec::new(),
|
||||
}
|
||||
|
||||
Argument: Name = {
|
||||
<name_start: @L> <v:"<var>"> <name_end: @L> =>
|
||||
Name::new(v, Location::new(file_idx, name_start..name_end)),
|
||||
}
|
||||
|
||||
OptionalComma: () = {
|
||||
=> (),
|
||||
"," => (),
|
||||
}
|
||||
|
||||
Statements: Vec<Statement> = {
|
||||
// a statement is either a set of statements followed by another
|
||||
// statement (note, here, that you can name the result of a sub-parse
|
||||
@@ -98,7 +134,7 @@ pub Statement: Statement = {
|
||||
e,
|
||||
),
|
||||
|
||||
// Alternatively, a statement can just be a print statement.
|
||||
// A statement can just be a print statement.
|
||||
<ls: @L> "print" <name_start: @L> <v:"<var>"> <name_end: @L> ";" <le: @L> =>
|
||||
Statement::Print(
|
||||
Location::new(file_idx, ls..le),
|
||||
@@ -166,6 +202,8 @@ AtomicExpression: Expression = {
|
||||
<l: @L> <v:"<var>"> <end: @L> => Expression::Reference(Location::new(file_idx, l..end), v.to_string()),
|
||||
// just a number
|
||||
<l: @L> <n:"<num>"> <end: @L> => Expression::Value(Location::new(file_idx, l..end), Value::Number(n.0, n.1, n.2)),
|
||||
// this expression could actually be a block!
|
||||
"{" <stmts:Statements> "}" => unimplemented!(),
|
||||
// finally, let people parenthesize expressions and get back to a
|
||||
// lower precedence
|
||||
"(" <e:Expression> ")" => e,
|
||||
|
||||
@@ -34,6 +34,9 @@ pub enum Token {
|
||||
#[token(";")]
|
||||
Semi,
|
||||
|
||||
#[token(",")]
|
||||
Comma,
|
||||
|
||||
#[token("(")]
|
||||
LeftParen,
|
||||
|
||||
@@ -46,6 +49,16 @@ pub enum Token {
|
||||
#[token(">")]
|
||||
GreaterThan,
|
||||
|
||||
#[token("{")]
|
||||
OpenBrace,
|
||||
|
||||
#[token("}")]
|
||||
CloseBrace,
|
||||
|
||||
#[token("lambda")]
|
||||
#[token("function")]
|
||||
Function,
|
||||
|
||||
// Next we take of any reserved words; I always like to put
|
||||
// these before we start recognizing more complicated regular
|
||||
// expressions. I don't think it matters, but it works for me.
|
||||
@@ -93,10 +106,14 @@ impl fmt::Display for Token {
|
||||
match self {
|
||||
Token::Equals => write!(f, "'='"),
|
||||
Token::Semi => write!(f, "';'"),
|
||||
Token::Comma => write!(f, "','"),
|
||||
Token::LeftParen => write!(f, "'('"),
|
||||
Token::RightParen => write!(f, "')'"),
|
||||
Token::LessThan => write!(f, "<"),
|
||||
Token::GreaterThan => write!(f, ">"),
|
||||
Token::OpenBrace => write!(f, "{{"),
|
||||
Token::CloseBrace => write!(f, "}}"),
|
||||
Token::Function => write!(f, "function"),
|
||||
Token::Print => write!(f, "'print'"),
|
||||
Token::Operator(c) => write!(f, "'{}'", c),
|
||||
Token::Number((None, otype, v)) => write!(f, "'{}{}'", v, display_optional_type(otype)),
|
||||
|
||||
Reference in New Issue
Block a user