feat: PHP simple assignment

master
Araozu 2024-08-01 15:21:08 -05:00
parent 4c565df699
commit 8e18458125
8 changed files with 101 additions and 10 deletions

View File

@ -0,0 +1,38 @@
use crate::{codegen::Transpilable, php_ast::PhpAssignmentExpression};
impl Transpilable for PhpAssignmentExpression<'_> {
fn transpile(&self) -> String {
match self {
PhpAssignmentExpression::Primary(p) => p.transpile(),
PhpAssignmentExpression::SimpleAssignment(assignment) => {
let variable_name = &assignment.variable;
let expression_str = assignment.assignment.transpile();
format!("${} = {}", variable_name, expression_str)
}
}
}
}
#[cfg(test)]
mod tests {
use crate::{
codegen::Transpilable,
php_ast::{PhpAssignmentExpression, PhpPrimaryExpression, PhpSimpleAssignment},
};
#[test]
fn should_gen_assignment() {
let variable = String::from("name");
let value = String::from("John");
let assignment = PhpPrimaryExpression::StringLiteral(&value);
let ast = PhpAssignmentExpression::SimpleAssignment(PhpSimpleAssignment {
variable,
assignment,
});
let output = ast.transpile();
assert_eq!("$name = \"John\"", output)
}
}

View File

@ -1 +1,2 @@
mod primary_expression; mod primary_expression;
mod assignment;

View File

@ -6,6 +6,7 @@ impl Transpilable for PhpPrimaryExpression<'_> {
PhpPrimaryExpression::IntegerLiteral(value) => value.to_string(), PhpPrimaryExpression::IntegerLiteral(value) => value.to_string(),
PhpPrimaryExpression::FloatingLiteral(value) => value.to_string(), PhpPrimaryExpression::FloatingLiteral(value) => value.to_string(),
PhpPrimaryExpression::StringLiteral(value) => format!("\"{}\"", value), PhpPrimaryExpression::StringLiteral(value) => format!("\"{}\"", value),
PhpPrimaryExpression::Variable(name) => format!("${}", name),
} }
} }
} }
@ -58,4 +59,13 @@ mod tests {
assert_eq!("322.644", output) assert_eq!("322.644", output)
} }
#[test]
fn should_transpile_variable() {
let input = String::from("name");
let ast = PhpPrimaryExpression::Variable(&input);
let output = ast.transpile();
assert_eq!("$name", output)
}
} }

View File

@ -8,7 +8,7 @@ pub mod statement_list;
impl Transpilable for PhpExpression<'_> { impl Transpilable for PhpExpression<'_> {
fn transpile(&self) -> String { fn transpile(&self) -> String {
match self { match self {
PhpExpression::PrimaryExpression(p) => p.transpile(), PhpExpression::Assignment(p) => p.transpile(),
} }
} }
} }

View File

@ -20,6 +20,10 @@ impl Transpilable for PhpStatement<'_> {
format!("echo {};", expressions_str) format!("echo {};", expressions_str)
} }
PhpStatement::PhpExpressionStatement(expr) => {
let expr_str = expr.transpile();
format!("{};", expr_str)
}
} }
} }
} }
@ -28,7 +32,10 @@ impl Transpilable for PhpStatement<'_> {
mod tests { mod tests {
use crate::{ use crate::{
codegen::Transpilable, codegen::Transpilable,
php_ast::{PhpExpression, PhpExpressionList, PhpPrimaryExpression, PhpStatement}, php_ast::{
PhpAssignmentExpression, PhpExpression, PhpExpressionList, PhpPrimaryExpression,
PhpStatement,
},
}; };
#[test] #[test]
@ -47,7 +54,9 @@ mod tests {
let input = String::from("322"); let input = String::from("322");
let exp_1 = PhpPrimaryExpression::FloatingLiteral(&input); let exp_1 = PhpPrimaryExpression::FloatingLiteral(&input);
let expressions = PhpExpressionList { let expressions = PhpExpressionList {
expressions: vec![PhpExpression::PrimaryExpression(exp_1)], expressions: vec![PhpExpression::Assignment(PhpAssignmentExpression::Primary(
exp_1,
))],
}; };
let ast = PhpStatement::PhpEchoStatement(expressions); let ast = PhpStatement::PhpEchoStatement(expressions);
let output = ast.transpile(); let output = ast.transpile();
@ -65,8 +74,8 @@ mod tests {
let expressions = PhpExpressionList { let expressions = PhpExpressionList {
expressions: vec![ expressions: vec![
PhpExpression::PrimaryExpression(exp_1), PhpExpression::Assignment(PhpAssignmentExpression::Primary(exp_1)),
PhpExpression::PrimaryExpression(exp_2), PhpExpression::Assignment(PhpAssignmentExpression::Primary(exp_2)),
], ],
}; };
let ast = PhpStatement::PhpEchoStatement(expressions); let ast = PhpStatement::PhpEchoStatement(expressions);
@ -74,4 +83,16 @@ mod tests {
assert_eq!("echo 322, \"Hai world\";", output) assert_eq!("echo 322, \"Hai world\";", output)
} }
#[test]
fn should_gen_expression_stmt() {
let input = String::from("Hi!");
let exp_1 = PhpPrimaryExpression::StringLiteral(&input);
let ast = PhpStatement::PhpExpressionStatement(PhpExpression::Assignment(
PhpAssignmentExpression::Primary(exp_1),
));
let output = ast.transpile();
assert_eq!("\"Hi!\";", output)
}
} }

View File

@ -19,6 +19,7 @@ pub struct PhpAst<'a> {
/// echo-statement /// echo-statement
pub enum PhpStatement<'a> { pub enum PhpStatement<'a> {
PhpEchoStatement(PhpExpressionList<'a>), PhpEchoStatement(PhpExpressionList<'a>),
PhpExpressionStatement(PhpExpression<'a>),
} }
pub struct PhpExpressionList<'a> { pub struct PhpExpressionList<'a> {
@ -26,15 +27,30 @@ pub struct PhpExpressionList<'a> {
} }
pub enum PhpExpression<'a> { pub enum PhpExpression<'a> {
PrimaryExpression(PhpPrimaryExpression<'a>), Assignment(PhpAssignmentExpression<'a>),
}
pub enum PhpAssignmentExpression<'a> {
Primary(PhpPrimaryExpression<'a>),
SimpleAssignment(PhpSimpleAssignment<'a>),
}
pub struct PhpSimpleAssignment<'a> {
pub variable: String,
pub assignment: PhpPrimaryExpression<'a>,
} }
/// https://phplang.org/spec/19-grammar.html#grammar-primary-expression /// https://phplang.org/spec/19-grammar.html#grammar-primary-expression
/// ///
/// primary-expression: /// primary-expression:
/// literal /// literal
/// variable
pub enum PhpPrimaryExpression<'a> { pub enum PhpPrimaryExpression<'a> {
IntegerLiteral(&'a String), IntegerLiteral(&'a String),
FloatingLiteral(&'a String), FloatingLiteral(&'a String),
StringLiteral(&'a String), StringLiteral(&'a String),
/// https://phplang.org/spec/19-grammar.html#grammar-variable
///
/// Supports only variable -> callable-variable -> simple-variable -> variable-name
Variable(&'a String),
} }

View File

@ -1,5 +1,8 @@
use super::super::PhpExpression; use super::super::PhpExpression;
use crate::{php_ast::PhpPrimaryExpression, syntax::ast::Expression}; use crate::{
php_ast::{PhpAssignmentExpression, PhpPrimaryExpression},
syntax::ast::Expression,
};
use super::PHPTransformable; use super::PHPTransformable;
@ -11,7 +14,7 @@ impl<'a> PHPTransformable<'a> for Expression<'_> {
match self { match self {
Expression::String(value) => { Expression::String(value) => {
let expr = PhpPrimaryExpression::StringLiteral(value); let expr = PhpPrimaryExpression::StringLiteral(value);
PhpExpression::PrimaryExpression(expr) PhpExpression::Assignment(PhpAssignmentExpression::Primary(expr))
} }
_ => todo!("transformation for expression: {:?}", self), _ => todo!("transformation for expression: {:?}", self),
} }

View File

@ -1,5 +1,7 @@
use super::super::PhpAst; use super::super::PhpAst;
use crate::php_ast::{PhpExpression, PhpExpressionList, PhpPrimaryExpression, PhpStatement}; use crate::php_ast::{
PhpAssignmentExpression, PhpExpression, PhpExpressionList, PhpPrimaryExpression, PhpStatement,
};
use crate::syntax::ast::{Expression, ModuleAST, ModuleMembers}; use crate::syntax::ast::{Expression, ModuleAST, ModuleMembers};
use super::PHPTransformable; use super::PHPTransformable;
@ -34,7 +36,7 @@ impl<'a> PHPTransformable<'a> for ModuleAST<'_> {
match e { match e {
Expression::String(v) => { Expression::String(v) => {
expressions.push( expressions.push(
PhpExpression::PrimaryExpression(PhpPrimaryExpression::StringLiteral(v)) PhpExpression::Assignment(PhpAssignmentExpression::Primary(PhpPrimaryExpression::StringLiteral(v)))
) )
}, },
_ => todo!("Non string expressions not supported") _ => todo!("Non string expressions not supported")