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: break & continue
  • Loading branch information
echosoar committed Feb 12, 2023
commit 2027ccb12051e2d5ff7a4adb5b36dd50b00631d7
73 changes: 71 additions & 2 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, ForStatement};
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, BreakStatement, ContinueStatement, LabeledStatement};
use crate::ast_utils::{get_hex_number_value, chars_to_string};
pub struct AST {
// 当前字符
Expand Down Expand Up @@ -109,6 +109,8 @@ impl AST{
Token::Var | Token::Let => self.parse_variable_statement(),
Token::If => self.parse_if_statement(),
Token::For => self.parse_for_statement(),
Token::Break => self.parse_break_statement(),
Token::Continue => self.parse_continue_statement(),
Token::Function => {
Statement::Function(self.parse_function(true))
},
Expand All @@ -123,8 +125,23 @@ impl AST{
},
_ => {
let expression = self.parse_expression();

// label:
if self.token == Token::Colon {
if let Expression::Identifier(identifier) = expression {
// TODO: 检测当前的作用域是否已经存在这个 lable,如果存在,则报错
// let label = identifier.literal;
self.next();
let statement = self.parse_statement();
return Statement::Label(LabeledStatement {
label: identifier,
statement: Box::new(statement),
});
}
}

match expression {
Expression::Unknown => {
Expression::Unknown => {
Statement::Unknown
},
_ => {
Expand Down Expand Up @@ -237,6 +254,58 @@ impl AST{
return Statement::For(statement);
}

fn parse_break_statement(&mut self) -> Statement {
self.check_token_and_next(Token::Break);
let mut semicolon = false;
// break;
if self.token == Token::Semicolon {
self.next();
semicolon = true;
}

// for() { break }
if semicolon || self.token == Token::RightBrace {
/*
TODO:
if self.scope.in_iteration || self.scope.in_switch {

} else {
// need label, throw error Illegal break statement
}
*/
return Statement::Break(BreakStatement {
label: None
});
}

self.check_token(Token::Identifier);
return Statement::Break(BreakStatement {
label: Some(IdentifierLiteral { literal: self.literal.clone() })
});
}

fn parse_continue_statement(&mut self) -> Statement {
self.check_token_and_next(Token::Continue);
let mut semicolon = false;
// continue;
if self.token == Token::Semicolon {
self.next();
semicolon = true;
}

// for() { continue }
if semicolon || self.token == Token::RightBrace {
return Statement::Continue(ContinueStatement {
label: None
});
}

self.check_token(Token::Identifier);
return Statement::Continue(ContinueStatement {
label: Some(IdentifierLiteral { literal: self.literal.clone() })
});
}

// 解析 function statement
fn parse_function(&mut self, variable_lifting: bool) -> FunctionDeclaration {
// 如果是 function 关键字,则跳过
Expand Down
55 changes: 47 additions & 8 deletions src/ast_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,20 @@ use crate::{ast_token::Token, value::Value, builtins::{object::Object}};

#[derive(Clone)]
pub enum Statement {
Var(VariableDeclarationStatement),
If(IfStatement),
// A -> Z
Block(BlockStatement),
Break(BreakStatement),
BuiltinFunction(BuiltinFunction),
Class(ClassDeclaration),
Continue(ContinueStatement),
Expression(ExpressionStatement),
For(ForStatement),
Function(FunctionDeclaration),
Class(ClassDeclaration),
Block(BlockStatement),
If(IfStatement),
Label(LabeledStatement),
Return(ReturnStatement),
Expression(ExpressionStatement),
BuiltinFunction(BuiltinFunction),
Unknown,
Unknown, // 未知
Var(VariableDeclarationStatement),
}

impl PartialEq for Statement {
Expand All @@ -32,7 +36,25 @@ impl PartialEq for Statement {

impl fmt::Debug for Statement {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "statement")
let mut stype = "unknown";
match self {
Statement::Block(_) => { stype = "block"},
Statement::Break(_) => { stype = "break"},
Statement::BuiltinFunction(_) => { stype = "builtin function"},
Statement::Class(_) => { stype = "class"},
Statement::Continue(_) => { stype = "continue"},
Statement::Expression(_) => { stype = "expression"},
Statement::For(_) => { stype = "for"},
Statement::Function(_) => { stype = "function"},
Statement::If(_) => { stype = "if"},
Statement::Label(_) => { stype = "label"},
Statement::Return(_) => { stype = "return"},
Statement::Var(_) => { stype = "var"},
_ => {
stype = "other"
},
}
write!(f, "{}", stype)
}
}

Expand Down Expand Up @@ -97,6 +119,13 @@ pub struct IfStatement {
pub else_statement: Box<Statement>,
}

#[derive(Debug, Clone, PartialEq)]
pub struct LabeledStatement {
pub label: IdentifierLiteral,
pub statement: Box<Statement>,
}


#[derive(Debug, Clone, PartialEq)]
pub struct ForStatement {
pub initializer: Box<Statement>,
Expand Down Expand Up @@ -147,6 +176,16 @@ pub struct ReturnStatement {
pub expression: Expression
}

#[derive(Debug, Clone, PartialEq)]
pub struct BreakStatement {
pub label: Option<IdentifierLiteral>
}

#[derive(Debug, Clone, PartialEq)]
pub struct ContinueStatement {
pub label: Option<IdentifierLiteral>
}

#[derive(Debug, Clone, PartialEq)]
pub struct Parameter {
pub name: IdentifierLiteral,
Expand Down
Loading