Skip to content

Commit

Permalink
Pretty printer
Browse files Browse the repository at this point in the history
Implement pretty printer and a test to confirm basics are working
  • Loading branch information
exilesprx committed Nov 21, 2023
1 parent 8b83d43 commit 803493b
Show file tree
Hide file tree
Showing 10 changed files with 177 additions and 13 deletions.
2 changes: 1 addition & 1 deletion .phpunit.result.cache
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"version":1,"defects":[],"times":{"Tests\\ScannerTest::it_expects_single_token_when_source_is_empty":0.005}}
{"version":1,"defects":{"Tests\\AstPrinterTest::it_expects_to_pretty_print_tree":7},"times":{"Tests\\ScannerTest::it_expects_single_token_when_source_is_empty":0.005,"Tests\\AstPrinterTest::it_expects_to_pretty_print_tree":0.03,"Tests\\AstPrinterTest::it_expects_missing_parenthesis_and_additional_space_not_to_match":0.004,"Tests\\AstPrinterTest::it_expects_the_printed_expression_to_match_exactly":0.002}}
112 changes: 112 additions & 0 deletions src/AstPrinter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
<?php

namespace Waffle;

use Waffle\Grammar\Expr;
use Waffle\Grammar\Expressions\Assign;
use Waffle\Grammar\Expressions\Binary;
use Waffle\Grammar\Expressions\Call;
use Waffle\Grammar\Expressions\EThis;
use Waffle\Grammar\Expressions\Get;
use Waffle\Grammar\Expressions\Grouping;
use Waffle\Grammar\Expressions\Literal;
use Waffle\Grammar\Expressions\Logical;
use Waffle\Grammar\Expressions\Set;
use Waffle\Grammar\Expressions\Super;
use Waffle\Grammar\Expressions\Unary;
use Waffle\Grammar\Expressions\Variable;

class AstPrinter implements Grammar\Expressions\Visitor
{
public function printExpr(Expr $expr): string
{
return $expr->accept($this);
}

public function visitAssignExpr(Assign $expr)
{
// TODO: Implement visitAssignExpr() method.
}

public function visitBinaryExpr(Binary $expr)
{
return $this->parenthesize(
$expr->operator->lexeme,
$expr->left,
$expr->right
);
}

public function visitCallExpr(Call $expr)
{
// TODO: Implement visitCallExpr() method.
}

public function visitGetExpr(Get $expr)
{
// TODO: Implement visitGetExpr() method.
}

public function visitGroupingExpr(Grouping $expr)
{
return $this->parenthesize(
"group",
$expr->expression
);
}

public function visitLiteralExpr(Literal $expr)
{
if (is_null($expr->value)) {
return "nil";
}
return (string)$expr->value;
}

public function visitLogicalExpr(Logical $expr)
{
// TODO: Implement visitLogicalExpr() method.
}

public function visitSetExpr(Set $expr)
{
// TODO: Implement visitSetExpr() method.
}

public function visitSuperExpr(Super $expr)
{
// TODO: Implement visitSuperExpr() method.
}

public function visitThisExpr(EThis $expr)
{
// TODO: Implement visitThisExpr() method.
}

public function visitUnaryExpr(Unary $expr)
{
return $this->parenthesize(
$expr->operator->lexeme,
$expr->right
);
}

public function visitVariableExpr(Variable $variable)
{
// TODO: Implement visitVariableExpr() method.
}

private function parenthesize(string $name, Expr...$exprs): string
{
$parts = [];
$parts[] = "(";
$parts[] = $name;
foreach ($exprs as $expr) {
$parts[] = " ";
$parts[] = $expr->accept($this);
}
$parts[] = ")";

return implode($parts);
}
}
7 changes: 4 additions & 3 deletions src/Grammar/Expressions/Binary.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
namespace Waffle\Grammar\Expressions;

use Waffle\Grammar\Expr;
use Waffle\Token;

class Binary extends Expr
{
public function __construct(
private readonly Expr $left,
private readonly Token $operator,
private readonly Expr $right
public readonly Expr $left,
public readonly Token $operator,
public readonly Expr $right
) {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use Waffle\Grammar\Expr;
use Waffle\Token;

class This extends Expr
class EThis extends Expr
{
public function __construct(
private readonly Token $keyword
Expand Down
2 changes: 1 addition & 1 deletion src/Grammar/Expressions/Grouping.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
class Grouping extends Expr
{
public function __construct(
private readonly Expr $grouping
public readonly Expr $expression
) {
}

Expand Down
2 changes: 1 addition & 1 deletion src/Grammar/Expressions/Literal.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
class Literal extends Expr
{
public function __construct(
private readonly mixed $value
public readonly mixed $value
) {
}

Expand Down
4 changes: 2 additions & 2 deletions src/Grammar/Expressions/Unary.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
class Unary extends Expr
{
public function __construct(
private readonly Token $operator,
private readonly Expr $right
public readonly Token $operator,
public readonly Expr $right
) {
}

Expand Down
2 changes: 1 addition & 1 deletion src/Grammar/Expressions/Visitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public function visitSetExpr(Set $expr);

public function visitSuperExpr(Super $expr);

public function visitThisExpr(This $expr);
public function visitThisExpr(EThis $expr);

public function visitUnaryExpr(Unary $expr);

Expand Down
5 changes: 2 additions & 3 deletions src/Token.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ class Token implements Stringable
{
public function __construct(
private TokenType $type,
private string $lexeme,
public readonly string $lexeme,
private mixed $literal,
private int $line
)
{
) {
}

public function __toString(): string
Expand Down
52 changes: 52 additions & 0 deletions tests/AstPrinterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

namespace Tests;

use PHPUnit\Framework\TestCase;
use Waffle\AstPrinter;
use Waffle\Grammar\Expr;
use Waffle\Grammar\Expressions\Binary;
use Waffle\Grammar\Expressions\Grouping;
use Waffle\Grammar\Expressions\Literal;
use Waffle\Grammar\Expressions\Unary;
use Waffle\Token;
use Waffle\TokenType;

class AstPrinterTest extends TestCase
{
private AstPrinter $printer;
private Expr $expr;

protected function setUp(): void
{
$this->printer = new AstPrinter();
$this->expr = new Binary(
new Unary(
new Token(TokenType::MINUS, "-", null, 1),
new Literal(123)
),
new Token(TokenType::STAR, "*", null, 1),
new Grouping(
new Literal(45.67)
)
);
}

/** @test */
public function it_expects_missing_parenthesis_and_additional_space_not_to_match(): void
{
$this->assertNotEquals(
"* (- 123) (group 45.67) )",
$this->printer->printExpr($this->expr)
);
}

/** @test */
public function it_expects_the_printed_expression_to_match_exactly(): void
{
$this->assertEquals(
"(* (- 123) (group 45.67))",
$this->printer->printExpr($this->expr)
);
}
}

0 comments on commit 803493b

Please sign in to comment.