Skip to content

[ExpressionLanguage] Added a way to dump the AST #19013

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

Merged
merged 1 commit into from
Jun 13, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions src/Symfony/Component/ExpressionLanguage/Node/ArgumentsNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,15 @@ public function compile(Compiler $compiler)
{
$this->compileArguments($compiler, false);
}

public function dump()
{
$str = '';

foreach ($this->getKeyValuePairs() as $pair) {
$str .= sprintf('%s, ', $pair['value']->dump());
}

return rtrim($str, ', ');
}
}
30 changes: 30 additions & 0 deletions src/Symfony/Component/ExpressionLanguage/Node/ArrayNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,36 @@ public function evaluate($functions, $values)
return $result;
}

public function dump()
{
$array = array();
foreach ($this->getKeyValuePairs() as $pair) {
$array[$pair['key']->attributes['value']] = $pair['value']->dump();
}

if ($this->isHash($array)) {
$str = '{';

foreach ($array as $key => $value) {
if (is_int($key)) {
$str .= sprintf('%s: %s, ', $key, $value);
} else {
$str .= sprintf('"%s": %s, ', $this->dumpEscaped($key), $value);
}
}

return rtrim($str, ', ').'}';
}

$str = '[';

foreach ($array as $key => $value) {
$str .= sprintf('%s, ', $value);
}

return rtrim($str, ', ').']';
}

protected function getKeyValuePairs()
{
$pairs = array();
Expand Down
5 changes: 5 additions & 0 deletions src/Symfony/Component/ExpressionLanguage/Node/BinaryNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -154,4 +154,9 @@ public function evaluate($functions, $values)
return preg_match($right, $left);
}
}

public function dump()
{
return sprintf('(%s %s %s)', $this->nodes['left']->dump(), $this->attributes['operator'], $this->nodes['right']->dump());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -48,4 +48,9 @@ public function evaluate($functions, $values)

return $this->nodes['expr3']->evaluate($functions, $values);
}

public function dump()
{
return sprintf('(%s ? %s : %s)', $this->nodes['expr1']->dump(), $this->nodes['expr2']->dump(), $this->nodes['expr3']->dump());
}
}
48 changes: 48 additions & 0 deletions src/Symfony/Component/ExpressionLanguage/Node/ConstantNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,52 @@ public function evaluate($functions, $values)
{
return $this->attributes['value'];
}

public function dump()
{
return $this->dumpValue($this->attributes['value']);
}

private function dumpValue($value)
{
switch (true) {
case true === $value:
return 'true';

case false === $value:
return 'false';

case null === $value:
return 'null';

case is_numeric($value):
return $value;

case is_array($value):
if ($this->isHash($value)) {
$str = '{';

foreach ($value as $key => $v) {
if (is_int($key)) {
$str .= sprintf('%s: %s, ', $key, $this->dumpValue($v));
} else {
$str .= sprintf('"%s": %s, ', $this->dumpEscaped($key), $this->dumpValue($v));
}
}

return rtrim($str, ', ').'}';
}

$str = '[';

foreach ($value as $key => $v) {
$str .= sprintf('%s, ', $this->dumpValue($v));
}

return rtrim($str, ', ').']';

default:
return sprintf('"%s"', $this->dumpEscaped($value));
}
}
}
13 changes: 13 additions & 0 deletions src/Symfony/Component/ExpressionLanguage/Node/FunctionNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,4 +49,17 @@ public function evaluate($functions, $values)

return call_user_func_array($functions[$this->attributes['name']]['evaluator'], $arguments);
}

public function dump()
{
$str = $this->attributes['name'];

$str .= '(';

foreach ($this->nodes['arguments']->nodes as $node) {
$str .= $node->dump().', ';
}

return rtrim($str, ', ').')';
}
}
14 changes: 14 additions & 0 deletions src/Symfony/Component/ExpressionLanguage/Node/GetAttrNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,4 +94,18 @@ public function evaluate($functions, $values)
return $array[$this->nodes['attribute']->evaluate($functions, $values)];
}
}

public function dump()
{
switch ($this->attributes['type']) {
case self::PROPERTY_CALL:
return sprintf('%s.%s', $this->nodes['node']->dump(), trim($this->nodes['attribute']->dump(), '"'));

case self::METHOD_CALL:
return sprintf('%s.%s(%s)', $this->nodes['node']->dump(), trim($this->nodes['attribute']->dump(), '"'), $this->nodes['arguments']->dump());

case self::ARRAY_CALL:
return sprintf('%s[%s]', $this->nodes['node']->dump(), $this->nodes['attribute']->dump());
}
}
}
5 changes: 5 additions & 0 deletions src/Symfony/Component/ExpressionLanguage/Node/NameNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,9 @@ public function evaluate($functions, $values)
{
return $values[$this->attributes['name']];
}

public function dump()
{
return $this->attributes['name'];
}
}
23 changes: 23 additions & 0 deletions src/Symfony/Component/ExpressionLanguage/Node/Node.php
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,27 @@ public function evaluate($functions, $values)

return $results;
}

public function dump()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should add a phpdoc here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other public method don't have PHPDoc... So it tried to be consistent here ;)

{
throw new \BadMethodCallException(sprintf('Dumping a "%s" instance is not supported yet.', get_class($this)));
}

protected function dumpEscaped($value)
{
return str_replace(array('\\', '"'), array('\\\\', '\"'), $value);
}

protected function isHash(array $value)
{
$expectedKey = 0;

foreach ($value as $key => $val) {
if ($key !== $expectedKey++) {
return true;
}
}

return false;
}
}
5 changes: 5 additions & 0 deletions src/Symfony/Component/ExpressionLanguage/Node/UnaryNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,9 @@ public function evaluate($functions, $values)

return $value;
}

public function dump()
{
return sprintf('(%s %s)', $this->attributes['operator'], $this->nodes['node']->dump());
}
}
5 changes: 5 additions & 0 deletions src/Symfony/Component/ExpressionLanguage/ParsedExpression.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,9 @@ public function getNodes()
{
return $this->nodes;
}

public function dump()
{
return $this->nodes->dump();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,14 @@ public function testCompile($expected, $node, $functions = array())
}

abstract public function getCompileData();

/**
* @dataProvider getDumpData
*/
public function testDump($expected, $node)
{
$this->assertSame($expected, $node->dump());
}

abstract public function getDumpData();
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ public function getCompileData()
);
}

public function getDumpData()
{
return array(
array('"a", "b"', $this->getArrayNode()),
);
}

protected function createArrayNode()
{
return new ArgumentsNode();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,21 @@ public function getCompileData()
);
}

public function getDumpData()
{
yield array('{"b": "a", 0: "b"}', $this->getArrayNode());

$array = $this->createArrayNode();
$array->addElement(new ConstantNode('c'), new ConstantNode('a"b'));
$array->addElement(new ConstantNode('d'), new ConstantNode('a\b'));
yield array('{"a\\"b": "c", "a\\\\b": "d"}', $array);

$array = $this->createArrayNode();
$array->addElement(new ConstantNode('c'));
$array->addElement(new ConstantNode('d'));
yield array('["c", "d"]', $array);
}

protected function getArrayNode()
{
$array = $this->createArrayNode();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,53 @@ public function getCompileData()
array('preg_match("/^[a-z]+/i\$/", "abc")', new BinaryNode('matches', new ConstantNode('abc'), new ConstantNode('/^[a-z]+/i$/'))),
);
}

public function getDumpData()
{
$array = new ArrayNode();
$array->addElement(new ConstantNode('a'));
$array->addElement(new ConstantNode('b'));

return array(
array('(true or false)', new BinaryNode('or', new ConstantNode(true), new ConstantNode(false))),
array('(true || false)', new BinaryNode('||', new ConstantNode(true), new ConstantNode(false))),
array('(true and false)', new BinaryNode('and', new ConstantNode(true), new ConstantNode(false))),
array('(true && false)', new BinaryNode('&&', new ConstantNode(true), new ConstantNode(false))),

array('(2 & 4)', new BinaryNode('&', new ConstantNode(2), new ConstantNode(4))),
array('(2 | 4)', new BinaryNode('|', new ConstantNode(2), new ConstantNode(4))),
array('(2 ^ 4)', new BinaryNode('^', new ConstantNode(2), new ConstantNode(4))),

array('(1 < 2)', new BinaryNode('<', new ConstantNode(1), new ConstantNode(2))),
array('(1 <= 2)', new BinaryNode('<=', new ConstantNode(1), new ConstantNode(2))),
array('(1 <= 1)', new BinaryNode('<=', new ConstantNode(1), new ConstantNode(1))),

array('(1 > 2)', new BinaryNode('>', new ConstantNode(1), new ConstantNode(2))),
array('(1 >= 2)', new BinaryNode('>=', new ConstantNode(1), new ConstantNode(2))),
array('(1 >= 1)', new BinaryNode('>=', new ConstantNode(1), new ConstantNode(1))),

array('(true === true)', new BinaryNode('===', new ConstantNode(true), new ConstantNode(true))),
array('(true !== true)', new BinaryNode('!==', new ConstantNode(true), new ConstantNode(true))),

array('(2 == 1)', new BinaryNode('==', new ConstantNode(2), new ConstantNode(1))),
array('(2 != 1)', new BinaryNode('!=', new ConstantNode(2), new ConstantNode(1))),

array('(1 - 2)', new BinaryNode('-', new ConstantNode(1), new ConstantNode(2))),
array('(1 + 2)', new BinaryNode('+', new ConstantNode(1), new ConstantNode(2))),
array('(2 * 2)', new BinaryNode('*', new ConstantNode(2), new ConstantNode(2))),
array('(2 / 2)', new BinaryNode('/', new ConstantNode(2), new ConstantNode(2))),
array('(5 % 2)', new BinaryNode('%', new ConstantNode(5), new ConstantNode(2))),
array('(5 ** 2)', new BinaryNode('**', new ConstantNode(5), new ConstantNode(2))),
array('("a" ~ "b")', new BinaryNode('~', new ConstantNode('a'), new ConstantNode('b'))),

array('("a" in ["a", "b"])', new BinaryNode('in', new ConstantNode('a'), $array)),
array('("c" in ["a", "b"])', new BinaryNode('in', new ConstantNode('c'), $array)),
array('("c" not in ["a", "b"])', new BinaryNode('not in', new ConstantNode('c'), $array)),
array('("a" not in ["a", "b"])', new BinaryNode('not in', new ConstantNode('a'), $array)),

array('(1 .. 3)', new BinaryNode('..', new ConstantNode(1), new ConstantNode(3))),

array('("abc" matches "/^[a-z]+/i$/")', new BinaryNode('matches', new ConstantNode('abc'), new ConstantNode('/^[a-z]+/i$/'))),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,12 @@ public function getCompileData()
array('((false) ? (1) : (2))', new ConditionalNode(new ConstantNode(false), new ConstantNode(1), new ConstantNode(2))),
);
}

public function getDumpData()
{
return array(
array('(true ? 1 : 2)', new ConditionalNode(new ConstantNode(true), new ConstantNode(1), new ConstantNode(2))),
array('(false ? 1 : 2)', new ConditionalNode(new ConstantNode(false), new ConstantNode(1), new ConstantNode(2))),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,20 @@ public function getCompileData()
array('array(0 => 1, "b" => "a")', new ConstantNode(array(1, 'b' => 'a'))),
);
}

public function getDumpData()
{
return array(
array('false', new ConstantNode(false)),
array('true', new ConstantNode(true)),
array('null', new ConstantNode(null)),
array(3, new ConstantNode(3)),
array(3.3, new ConstantNode(3.3)),
array('"foo"', new ConstantNode('foo')),
array('{0: 1, "b": "a", 1: true}', new ConstantNode(array(1, 'b' => 'a', true))),
array('{"a\\"b": "c", "a\\\\b": "d"}', new ConstantNode(array('a"b' => 'c', 'a\\b' => 'd'))),
array('["c", "d"]', new ConstantNode(array('c', 'd'))),
array('{"a": ["b"]}', new ConstantNode(array('a' => array('b')))),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,13 @@ public function getCompileData()
);
}

public function getDumpData()
{
return array(
array('foo("bar")', new FunctionNode('foo', new Node(array(new ConstantNode('bar')))), array('foo' => $this->getCallables())),
);
}

protected function getCallables()
{
return array(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,19 @@ public function getCompileData()
);
}

public function getDumpData()
{
return array(
array('foo[0]', new GetAttrNode(new NameNode('foo'), new ConstantNode(0), $this->getArrayNode(), GetAttrNode::ARRAY_CALL)),
array('foo["b"]', new GetAttrNode(new NameNode('foo'), new ConstantNode('b'), $this->getArrayNode(), GetAttrNode::ARRAY_CALL)),

array('foo.foo', new GetAttrNode(new NameNode('foo'), new ConstantNode('foo'), $this->getArrayNode(), GetAttrNode::PROPERTY_CALL), array('foo' => new Obj())),

array('foo.foo({"b": "a", 0: "b"})', new GetAttrNode(new NameNode('foo'), new ConstantNode('foo'), $this->getArrayNode(), GetAttrNode::METHOD_CALL), array('foo' => new Obj())),
array('foo[index]', new GetAttrNode(new NameNode('foo'), new NameNode('index'), $this->getArrayNode(), GetAttrNode::ARRAY_CALL)),
);
}

protected function getArrayNode()
{
$array = new ArrayNode();
Expand Down
Loading