Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: condition #6

Merged
merged 14 commits into from
Feb 20, 2023
Prev Previous commit
Next Next commit
feat: for
  • Loading branch information
echosoar committed Feb 9, 2023
commit 68d770359034fcdde752e8606a0914cd1fec0ac4
61 changes: 54 additions & 7 deletions src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
use std::io;

use crate::ast_token::{get_token_keyword, Token, get_token_literal};
use crate::ast_node::{ Expression, NumberLiteral, StringLiteral, Statement, IdentifierLiteral, ExpressionStatement, PropertyAccessExpression, BinaryExpression, ConditionalExpression, CallExpression, Keywords, Parameter, BlockStatement, ReturnStatement, Declaration, PropertyAssignment, ObjectLiteral, ElementAccessExpression, FunctionDeclaration, PostfixUnaryExpression, PrefixUnaryExpression, AssignExpression, GroupExpression, VariableDeclaration, VariableDeclarationStatement, VariableFlag, ClassDeclaration, ClassMethodDeclaration, ArrayLiteral, ComputedPropertyName, IfStatement};
use crate::ast_node::{ Expression, NumberLiteral, StringLiteral, Statement, IdentifierLiteral, ExpressionStatement, PropertyAccessExpression, BinaryExpression, ConditionalExpression, CallExpression, Keywords, Parameter, BlockStatement, ReturnStatement, Declaration, PropertyAssignment, ObjectLiteral, ElementAccessExpression, FunctionDeclaration, PostfixUnaryExpression, PrefixUnaryExpression, AssignExpression, GroupExpression, VariableDeclaration, VariableDeclarationStatement, VariableFlag, ClassDeclaration, ClassMethodDeclaration, ArrayLiteral, ComputedPropertyName, IfStatement, ForStatement};
use crate::ast_utils::{get_hex_number_value, chars_to_string};
pub struct AST {
// 当前字符
Expand Down Expand Up @@ -108,6 +108,7 @@ impl AST{
match self.token {
Token::Var | Token::Let => self.parse_variable_statement(),
Token::If => self.parse_if_statement(),
Token::For => self.parse_for_statement(),
Token::Function => {
Statement::Function(self.parse_function(true))
},
Expand Down Expand Up @@ -147,25 +148,29 @@ impl AST{
self.check_token_and_next(Token::Var);
}

let mut var_statement = VariableDeclarationStatement {
list: vec![],
let var_statement = VariableDeclarationStatement {
list: self.parse_variable_declarations(),
flag: variable_flag,
};
self.semicolon();
return Statement::Var(var_statement);
}

fn parse_variable_declarations(&mut self) -> Vec<Expression> {
let mut list: Vec<Expression> = vec![];
loop {
let expression = self.parse_variable_declaration();
var_statement.list.push(expression);
list.push(expression);
// let a= 1, b = 2;
if self.token != Token::Comma {
break;
}
self.next();
}
self.semicolon();
return Statement::Var(var_statement);
list
}



// 解析 block statement
fn parse_block_statement(&mut self) -> Statement {
// 以左花括号开始
Expand Down Expand Up @@ -201,6 +206,48 @@ impl AST{
return Statement::If(statement)
}

// 解析 for 循环
// TODO: for in/ of
fn parse_for_statement(&mut self) -> Statement {
self.check_token_and_next(Token::For);
self.check_token_and_next(Token::LeftParenthesis);
// 解析 initializer
// 需要额外处理 var 的情况
let mut initializer = Statement::Unknown;
if self.token == Token::Var || self.token == Token::Let {
initializer = self.parse_variable_statement();
} else if self.token != Token::Semicolon {
initializer = Statement::Expression(ExpressionStatement { expression: self.parse_expression() })
}
// TODO: self.check_token_and_next(Token::Semicolon);
let codition = self.parse_expression();
println!("codition: {:?} {:?}", codition, self.token);
self.check_token_and_next(Token::Semicolon);
let incrementor = self.parse_expression();
self.check_token_and_next(Token::RightParenthesis);
println!("incrementor: {:?} {:?}", incrementor , self.token);
let statement = ForStatement {
initializer: Box::new(initializer),
codition: codition,
incrementor: incrementor,
statement: Box::new(Statement::Unknown),
};
// self.check_token_and_next(Token::RightParenthesis);
// // 判断是否是 单行if
// if self.token == Token::LeftBrace {
// statement.then_statement = Box::new(self.parse_block_statement());
// } else {
// statement.then_statement = Box::new(self.parse_statement());
// }

// if self.token == Token::Else {
// self.next();
// statement.else_statement = Box::new(self.parse_statement());
// }
// return Statement::If(statement)
return Statement::For(statement);
}

// 解析 function statement
fn parse_function(&mut self, variable_lifting: bool) -> FunctionDeclaration {
// 如果是 function 关键字,则跳过
Expand Down
9 changes: 9 additions & 0 deletions src/ast_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::{ast_token::Token, value::Value, builtins::{object::Object}};
pub enum Statement {
Var(VariableDeclarationStatement),
If(IfStatement),
For(ForStatement),
Function(FunctionDeclaration),
Class(ClassDeclaration),
Block(BlockStatement),
Expand Down Expand Up @@ -96,6 +97,14 @@ pub struct IfStatement {
pub else_statement: Box<Statement>,
}

#[derive(Debug, Clone, PartialEq)]
pub struct ForStatement {
pub initializer: Box<Statement>,
pub codition: Expression,
pub incrementor: Expression,
pub statement: Box<Statement>,
}



#[derive(Debug, Clone, PartialEq)]
Expand Down
14 changes: 13 additions & 1 deletion tests/confitional_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use jsi::{JSI, value::Value};

#[test]
fn run_function_instances_has_class() {
fn run_if_else() {
let mut jsi = JSI::new();
let result = jsi.run(String::from("\
let a = false;
Expand All @@ -14,4 +14,16 @@ fn run_function_instances_has_class() {
}\n
b"));
assert_eq!(result , Value::Number(2f64));
}

#[test]
fn run_for() {
let mut jsi = JSI::new();
let result = jsi.run(String::from("\
let a = [];
for(let i = 0; i < 3; i++) {
a.push(i);
}\n
a.join(':')"));
assert_eq!(result , Value::String(String::from("0:1:2")));
}