use super::Parser;
use crate::syntax::{
ast::{
node::{
field::GetConstField, Assign, BinOp, Call, FunctionDecl, Identifier, New, Node, Return,
StatementList, UnaryOp, VarDecl, VarDeclList,
},
op::{self, NumOp},
Const,
},
lexer::Lexer,
};
#[allow(clippy::result_unwrap_used)]
pub(super) fn check_parser<L>(js: &str, expr: L)
where
L: Into<Box<[Node]>>,
{
let mut lexer = Lexer::new(js);
lexer.lex().expect("failed to lex");
assert_eq!(
Parser::new(&lexer.tokens)
.parse_all()
.expect("failed to parse"),
StatementList::from(expr)
);
}
pub(super) fn check_invalid(js: &str) {
let mut lexer = Lexer::new(js);
lexer.lex().expect("failed to lex");
assert!(Parser::new(&lexer.tokens).parse_all().is_err());
}
#[test]
fn check_construct_call_precedence() {
check_parser(
"new Date().getTime()",
vec![Node::from(Call::new(
GetConstField::new(
New::from(Call::new(Identifier::from("Date"), vec![])),
"getTime",
),
vec![],
))],
);
}
#[test]
fn assign_operator_precedence() {
check_parser(
"a = a + 1",
vec![Assign::new(
Identifier::from("a"),
BinOp::new(NumOp::Add, Identifier::from("a"), Const::from(1)),
)
.into()],
);
}
#[test]
fn hoisting() {
check_parser(
r"
var a = hello();
a++;
function hello() { return 10 }",
vec![
FunctionDecl::new(
Box::from("hello"),
vec![],
vec![Return::new(Const::from(10), None).into()],
)
.into(),
VarDeclList::from(vec![VarDecl::new(
"a",
Node::from(Call::new(Identifier::from("hello"), vec![])),
)])
.into(),
UnaryOp::new(op::UnaryOp::IncrementPost, Identifier::from("a")).into(),
],
);
check_parser(
r"
a = 10;
a++;
var a;",
vec![
Assign::new(Identifier::from("a"), Const::from(10)).into(),
UnaryOp::new(op::UnaryOp::IncrementPost, Identifier::from("a")).into(),
VarDeclList::from(vec![VarDecl::new("a", None)]).into(),
],
);
}