variable bindings

This commit is contained in:
greg 2017-09-17 06:04:24 -07:00
parent 1981b74d89
commit b920fae93b

View File

@ -327,7 +327,7 @@ program := (statement delimiter)* EOF
delimiter := NEWLINE | ';' delimiter := NEWLINE | ';'
statement := expression | declaration statement := expression | declaration
declaration := type_alias | type_declaration | func_declaration declaration := type_alias | type_declaration | func_declaration | binding_declaration
type_alias := 'alias' IDENTIFIER '=' IDENTIFIER type_alias := 'alias' IDENTIFIER '=' IDENTIFIER
type_declaration := 'type' IDENTIFIER '=' type_body type_declaration := 'type' IDENTIFIER '=' type_body
@ -338,6 +338,9 @@ member_list := (IDENTIFIER type_anno)*
func_declaration := 'fn' IDENTIFIER '(' param_list ')' func_declaration := 'fn' IDENTIFIER '(' param_list ')'
param_list := (IDENTIFIER type_anno+ ',')* param_list := (IDENTIFIER type_anno+ ',')*
binding_declaration: 'var' IDENTIFIER '=' expression
| 'const' IDENTIFIER '=' expression
type_anno := ':' type type_anno := ':' type
expression := precedence_expr expression := precedence_expr
@ -435,7 +438,12 @@ pub enum Declaration {
params: FormalParamList, params: FormalParamList,
}, },
TypeDecl(Rc<String>, TypeBody), TypeDecl(Rc<String>, TypeBody),
TypeAlias(Rc<String>, Rc<String>) TypeAlias(Rc<String>, Rc<String>),
Binding {
name: Rc<String>,
constant: bool,
expr: Expression,
}
} }
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
@ -522,6 +530,7 @@ impl Parser {
Keyword(Alias) => self.type_alias().map(|alias| { Statement::Declaration(alias) }), Keyword(Alias) => self.type_alias().map(|alias| { Statement::Declaration(alias) }),
Keyword(Type) => self.type_declaration().map(|decl| { Statement::Declaration(decl) }), Keyword(Type) => self.type_declaration().map(|decl| { Statement::Declaration(decl) }),
Keyword(Func)=> self.func_declaration().map(|func| { Statement::Declaration(func) }), Keyword(Func)=> self.func_declaration().map(|func| { Statement::Declaration(func) }),
Keyword(Var) | Keyword(Const) => self.binding_declaration().map(|decl| Statement::Declaration(decl)),
_ => self.expression().map(|expr| { Statement::Expression(expr) } ), _ => self.expression().map(|expr| { Statement::Expression(expr) } ),
} }
}); });
@ -564,6 +573,19 @@ impl Parser {
Ok(vec!()) Ok(vec!())
}); });
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()?;
expect!(self, Operator(ref o) if **o == "=", "Expected '='");
let expr = self.expression()?;
Ok(Declaration::Binding { name, constant, expr })
});
parse_method!(expression(&mut self) -> ParseResult<Expression> { parse_method!(expression(&mut self) -> ParseResult<Expression> {
self.precedence_expr(Operation::min_precedence()) self.precedence_expr(Operation::min_precedence())
}); });
@ -846,7 +868,7 @@ mod parse_tests {
} }
#[test] #[test]
fn parse_complicated_operators() { fn parsing_complicated_operators() {
parse_test!("a <- b", AST(vec![Expression(binexp!(op!("<-"), var!("a"), var!("b")))])); parse_test!("a <- b", AST(vec![Expression(binexp!(op!("<-"), var!("a"), var!("b")))]));
parse_test!("a || b", AST(vec![Expression(binexp!(op!("||"), var!("a"), var!("b")))])); parse_test!("a || b", AST(vec![Expression(binexp!(op!("||"), var!("a"), var!("b")))]));
parse_test!("a<>b", AST(vec![Expression(binexp!(op!("<>"), var!("a"), var!("b")))])); parse_test!("a<>b", AST(vec![Expression(binexp!(op!("<>"), var!("a"), var!("b")))]));
@ -868,7 +890,7 @@ mod parse_tests {
} }
#[test] #[test]
fn parse_bools() { fn parsing_bools() {
parse_test!("false", AST(vec![Expression(BoolLiteral(false))])); parse_test!("false", AST(vec![Expression(BoolLiteral(false))]));
parse_test!("true", AST(vec![Expression(BoolLiteral(true))])); parse_test!("true", AST(vec![Expression(BoolLiteral(true))]));
} }
@ -883,4 +905,10 @@ mod parse_tests {
parse_test!("type Yolo = Yolo", AST(vec![Declaration(TypeDecl(rc!(Yolo), TypeBody(vec![Variant::Singleton(rc!(Yolo))])))])); parse_test!("type Yolo = Yolo", AST(vec![Declaration(TypeDecl(rc!(Yolo), TypeBody(vec![Variant::Singleton(rc!(Yolo))])))]));
parse_test!("alias Sex = Drugs", AST(vec![Declaration(TypeAlias(rc!(Sex), rc!(Drugs)))])); parse_test!("alias Sex = Drugs", AST(vec![Declaration(TypeAlias(rc!(Sex), rc!(Drugs)))]));
} }
#[test]
fn parsing_bindings() {
parse_test!("var a = 10", AST(vec![Declaration(Binding { name: rc!(a), constant: false, expr: IntLiteral(10) } )]));
parse_test!("const a = 2 + 2", AST(vec![Declaration(Binding { name: rc!(a), constant: true, expr: binexp!(op!("+"), IntLiteral(2), IntLiteral(2)) }) ]));
}
} }