Skip to content

Commit

Permalink
Merge pull request #27 from psl-lang/feature/while
Browse files Browse the repository at this point in the history
while 구문 구현
  • Loading branch information
RanolP authored Nov 21, 2023
2 parents 6ceac3c + 5806d42 commit f200be7
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 6 deletions.
9 changes: 8 additions & 1 deletion crates/psl/src/ast/statements.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
use super::{Declaration, Expression, NameExpression};
use super::{Block, Declaration, Expression, NameExpression};

#[derive(Clone, Debug, Hash, PartialEq)]
pub enum Statement {
Declaration(Declaration),
Write(WriteStatement),
While(WhileStatement),
Expression(Expression),
}

#[derive(Clone, Debug, Hash, PartialEq)]
pub struct WriteStatement {
pub name: NameExpression,
}

#[derive(Clone, Debug, Hash, PartialEq)]
pub struct WhileStatement {
pub condition: Expression,
pub block: Block,
}
6 changes: 4 additions & 2 deletions crates/psl/src/ast/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ pub enum TokenKind {
LiteralIntegerHexadecimal,
LiteralIntegerBinary,

// please sort keyword alphabetically
KeywordElse,
KeywordIf,
KeywordRead,
KeywordWhile,
KeywordWrite,
KeywordIf,
KeywordElse,

// please sort punctuation by its ascii code
// please name enum variant Punctuation (PascalCase-d unicode name[1])
Expand Down
3 changes: 3 additions & 0 deletions crates/psl/src/codegen/impls/statements/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod r#while;
mod write;

use crate::{
Expand All @@ -13,6 +14,7 @@ impl CodegenNode for Statement {
match self {
Statement::Declaration(node) => ctx.visit(node),
Statement::Write(node) => ctx.visit(node),
Statement::While(node) => ctx.visit(node),
Statement::Expression(node) => format!("{};", ctx.visit(node)),
}
}
Expand All @@ -23,6 +25,7 @@ impl NameResolutionPass for Statement {
match self {
Statement::Declaration(node) => ctx.visit(node),
Statement::Write(node) => ctx.visit(node),
Statement::While(node) => ctx.visit(node),
Statement::Expression(node) => ctx.visit(node),
}
}
Expand Down
38 changes: 38 additions & 0 deletions crates/psl/src/codegen/impls/statements/while.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use crate::{
ast::WhileStatement,
codegen::{
context::CodegenContext,
pass::{NameResolutionContext, NameResolutionPass},
visitor::CodegenNode,
},
};

impl CodegenNode for WhileStatement {
fn produce_code(self, ctx: &mut CodegenContext) -> String {
let mut output = String::new();

output.push_str("while (");
output.push_str(&ctx.visit(self.condition));
output.push_str(") {\n");
for statement in self.block.statements {
output.push_str(&ctx.visit(statement));
}
if let Some(last_expression) = self.block.last_expression {
output.push_str(&format!("{};\n", ctx.visit(last_expression)));
}
output.push_str("}\n");

output
}
}

impl NameResolutionPass for WhileStatement {
fn resolve(&self, ctx: &mut NameResolutionContext) {
let mut scope = ctx.create_subscope();
scope.visit(&self.condition);
for statement in &self.block.statements {
ctx.visit(statement);
}
ctx.visit(&self.block.last_expression)
}
}
4 changes: 3 additions & 1 deletion crates/psl/src/syntax/statements/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod r#while;
mod write;

use winnow::{
Expand All @@ -7,7 +8,7 @@ use winnow::{

use crate::ast::Statement;

use self::write::parse_write;
use self::{r#while::parse_while, write::parse_write};

use super::{
declarations::parse_declaration, expressions::parse_expression,
Expand All @@ -18,6 +19,7 @@ pub fn parse_statement(s: &mut Located<&str>) -> PResult<Statement> {
alt((
parse_declaration.map(Statement::Declaration),
parse_write.map(Statement::Write),
parse_while.map(Statement::While),
terminated(parse_expression, opt(parse_separator)).map(Statement::Expression),
))
.parse_next(s)
Expand Down
25 changes: 25 additions & 0 deletions crates/psl/src/syntax/statements/while.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
use winnow::{
combinator::{cut_err, opt},
Located, PResult, Parser,
};

use crate::{
ast::{TokenKind, WhileStatement},
syntax::{
expressions::parse_expression,
fragments::{block::parse_block, separator::parse_separator},
},
};

pub fn parse_while(s: &mut Located<&str>) -> PResult<WhileStatement> {
(
TokenKind::KeywordWhile,
opt(TokenKind::WhitespaceHorizontal),
cut_err(parse_expression),
opt(TokenKind::WhitespaceHorizontal),
parse_block,
parse_separator,
)
.map(|(_, _, condition, _, block, _)| WhileStatement { condition, block })
.parse_next(s)
}
6 changes: 4 additions & 2 deletions crates/psl/src/syntax/tokens/keyword.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@ use crate::ast::{Token, TokenKind};
use super::token;

pub fn parse_keyword(s: &mut Located<&str>) -> PResult<Token> {
// please sort alt by enum declaration order
alt((
tag("else").with_span().map(token(TokenKind::KeywordElse)),
tag("if").with_span().map(token(TokenKind::KeywordIf)),
tag("read").with_span().map(token(TokenKind::KeywordRead)),
tag("write").with_span().map(token(TokenKind::KeywordWrite)),
tag("if").with_span().map(token(TokenKind::KeywordIf)),
tag("else").with_span().map(token(TokenKind::KeywordElse)),
tag("while").with_span().map(token(TokenKind::KeywordWhile)),
))
.parse_next(s)
}

0 comments on commit f200be7

Please sign in to comment.