first commit

This commit is contained in:
2024-07-15 12:33:27 +02:00
commit ce50ae282b
22084 changed files with 2623791 additions and 0 deletions

View File

@@ -0,0 +1,320 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax;
/**
* Comments registry class. Internal class used to manage comments
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class CommentsRegistry
{
/**
* Map of the indices where nodes start
*
* @var int
*/
protected $nodesStartMap = array();
/**
* Map of the indices where nodes end
*
* @var int
*/
protected $nodesEndMap = array();
/**
* Comments buffer
*
* @var array
*/
protected $buffer = null;
/**
* Last token index
*
* @var int
*/
protected $lastTokenIndex = null;
/**
* Comments registry
*
* @var array
*/
protected $registry = array();
/**
* Class constructor
*
* @param Parser $parser Parser
*/
public function __construct(Parser $parser)
{
$parser->getEventsEmitter()
->addListener("NodeCompleted", array($this, "onNodeCompleted"))
->addListener("EndParsing", array($this, "onEndParsing"));
$parser->getScanner()->getEventsEmitter()
->addListener("TokenConsumed", array($this, "onTokenConsumed"))
->addListener("EndReached", array($this, "onTokenConsumed"))
->addListener("FreezeState", array($this, "onScannerFreezeState"))
->addListener("ResetState", array($this, "onScannerResetState"));
}
/**
* Listener called every time the scanner compose the array that represents
* its current state
*
* @param array $state State
*
* @return void
*/
public function onScannerFreezeState(&$state)
{
//Register the current last token index
$state["commentsLastTokenIndex"] = $this->lastTokenIndex;
}
/**
* Listener called every time the scanner reset its state using the given
* array
*
* @param array $state State
*
* @return void
*/
public function onScannerResetState(&$state)
{
//Reset the last token index and delete it from the state array
$this->lastTokenIndex = $state["commentsLastTokenIndex"];
unset($state["commentsLastTokenIndex"]);
}
/**
* Listener called every time a token is consumed and when the scanner
* reaches the end of the source
*
* @param Token|null $token Consumed token or null if the end has
* been reached
*
* @return void
*/
public function onTokenConsumed(Token $token = null)
{
//Check if it's a comment
if ($token && $token->type === Token::TYPE_COMMENT) {
//If there is not an open comments buffer, create it
if (!$this->buffer) {
$this->buffer = array(
"prev" => $this->lastTokenIndex,
"next" => null,
"comments" => array()
);
}
//Add the comment token to the buffer
$this->buffer["comments"][] = $token;
} else {
if ($token) {
$loc = $token->location;
//Store the token end position
$this->lastTokenIndex = $loc->end->getIndex();
if ($this->buffer) {
//Fill the "next" key on the comments buffer with the token
//start position
$this->buffer["next"] = $loc->start->getIndex();
}
}
//If there is an open comment buffer, close it and move it to the
//registry
if ($buffer = $this->buffer) {
//Use the location as key to add the group of comments to the
//registry, in this way if comments are reprocessed they won't
//be duplicated
$key = implode("-", array(
$buffer["prev"] !== null ? $buffer["prev"] : "",
$buffer["next"] !== null ? $buffer["next"] : ""
));
$this->registry[$key] = $this->buffer;
$this->buffer = null;
}
}
}
/**
* Listener called every time a node is completed by the parser
*
* @param Node\Node $node Completed node
*
* @return void
*/
public function onNodeCompleted(Node\Node $node)
{
//Every time a node is completed, register its start and end indices
//in the relative properties
$loc = $node->location;
foreach (array("Start", "End") as $pos) {
$val = $loc->{"get$pos"}()->getIndex();
$map = &$this->{"nodes{$pos}Map"};
if (!isset($map[$val])) {
$map[$val] = array();
}
$map[$val][] = $node;
}
}
/**
* Listener called when parsing process ends
*
* @return void
*/
public function onEndParsing()
{
//Return if there are no comments to process
if ($this->registry) {
//Make sure nodes start indices map is sorted
ksort($this->nodesStartMap);
//Loop all comment groups in the registry
foreach ($this->registry as $group) {
$this->findNodeForCommentsGroup($group);
}
}
}
/**
* Finds the node to attach the given comments group
*
* @param array $group Comments group
*
* @return void
*/
public function findNodeForCommentsGroup($group)
{
$next = $group["next"];
$prev = $group["prev"];
$comments = $group["comments"];
$leading = true;
//If the group of comments has a next token index that appears
//in the map of start node indices, add the group to the
//corresponding node's leading comments. This associates
//comments that appear immediately before a node.
//For example: /*comment*/ for (;;){}
if (isset($this->nodesStartMap[$next])) {
$nodes = $this->nodesStartMap[$next];
}
//If the group of comments has a previous token index that appears
//in the map of end node indices, add the group to the
//corresponding node's trailing comments. This associates
//comments that appear immediately after a node.
//For example: for (;;){} /*comment*/
elseif (isset($this->nodesEndMap[$prev])) {
$nodes = $this->nodesEndMap[$prev];
$leading = false;
}
//Otherwise, find a node that wraps the comments position.
//This associates inner comments:
//For example: for /*comment*/ (;;){}
else {
//Calculate comments group boundaries
$start = $comments[0]->location->start->getIndex();
$end = $comments[count($comments) -1]->location->end->getIndex();
$nodes = array();
//Loop all the entries in the start index map
foreach ($this->nodesStartMap as $idx => $ns) {
//If the index is higher than the start index of the comments
//group, stop
if ($idx > $start) {
break;
}
foreach ($ns as $node) {
//Check if the comments group is inside node indices range
if ($node->location->end->getIndex() >= $end) {
$nodes[] = $node;
}
}
}
//If comments can't be associated with any node, associate it as
//leading comments of the program, this happens when the source is
//empty
if (!$nodes) {
$firstNode = array_values($this->nodesStartMap);
$nodes = array($firstNode[0][0]);
}
}
//If there are multiple possible nodes to associate the comments to,
//find the shortest one
if (count($nodes) > 1) {
usort($nodes, array($this, "compareNodesLength"));
}
$this->associateComments($nodes[0], $comments, $leading);
}
/**
* Compares node length
*
* @param Node\Node $node1 First node
* @param Node\Node $node2 Second node
*
* @return int
*
* @codeCoverageIgnore
*/
public function compareNodesLength($node1, $node2)
{
$loc1 = $node1->location;
$length1 = $loc1->end->getIndex() - $loc1->start->getIndex();
$loc2 = $node2->location;
$length2 = $loc2->end->getIndex() - $loc2->start->getIndex();
//If the nodes have the same length make sure to choose nodes
//different from Program nodes
if ($length1 === $length2) {
if ($node1 instanceof Node\Program) {
$length1 += 1000;
} elseif ($node2 instanceof Node\Program) {
$length2 += 1000;
}
}
return $length1 < $length2 ? -1 : 1;
}
/**
* Adds comments to the given node
*
* @param Node\Node $node Node
* @param array $comments Array of comments to add
* @param bool $leading True to add comments as leading comments
* or false to add them as trailing comments
*
* @return void
*/
public function associateComments($node, $comments, $leading)
{
$fn = ($leading ? "Leading" : "Trailing") . "Comments";
$currentComments = $node->{"get$fn"}();
foreach ($comments as $comment) {
$loc = $comment->location;
$commentNode = new Node\Comment;
$commentNode->location->start = $loc->start;
$commentNode->location->end = $loc->end;
$commentNode->setRawText($comment->value);
$currentComments[] = $commentNode;
}
$node->{"set$fn"}($currentComments);
}
}

View File

@@ -0,0 +1,21 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\ES2015;
/**
* ES2015 features class
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*
* @codeCoverageIgnore
*/
class Features extends \Peast\Syntax\Features
{
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\ES2016;
/**
* ES2016 features class
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*
* @codeCoverageIgnore
*/
class Features extends \Peast\Syntax\ES2015\Features
{
/**
* Exponentiation operator
*
* @var bool
*/
public $exponentiationOperator = true;
}

View File

@@ -0,0 +1,41 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\ES2017;
/**
* ES2017 features class
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*
* @codeCoverageIgnore
*/
class Features extends \Peast\Syntax\ES2016\Features
{
/**
* Async/await
*
* @var bool
*/
public $asyncAwait = true;
/**
* Trailing comma in function calls and declarations
*
* @var bool
*/
public $trailingCommaFunctionCallDeclaration = true;
/**
* For-in initializer
*
* @var bool
*/
public $forInInitializer = true;
}

View File

@@ -0,0 +1,41 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\ES2018;
/**
* ES2018 features class
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*
* @codeCoverageIgnore
*/
class Features extends \Peast\Syntax\ES2017\Features
{
/**
* Async iteration and generators
*
* @var bool
*/
public $asyncIterationGenerators = true;
/**
* Rest/spread properties
*
* @var bool
*/
public $restSpreadProperties = true;
/**
* Skip escape sequences checks in tagged template
*
* @var bool
*/
public $skipEscapeSeqCheckInTaggedTemplates = true;
}

View File

@@ -0,0 +1,34 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\ES2019;
/**
* ES2019 features class
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*
* @codeCoverageIgnore
*/
class Features extends \Peast\Syntax\ES2018\Features
{
/**
* Optional catch binding
*
* @var bool
*/
public $optionalCatchBinding = true;
/**
* Paragraph and line separator in strings
*
* @var bool
*/
public $paragraphLineSepInStrings = true;
}

View File

@@ -0,0 +1,62 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\ES2020;
/**
* ES2020 features class
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*
* @codeCoverageIgnore
*/
class Features extends \Peast\Syntax\ES2019\Features
{
/**
* Dynamic import
*
* @var bool
*/
public $dynamicImport = true;
/**
* BigInt literals
*
* @var bool
*/
public $bigInt = true;
/**
* Exported name for export all declarations
*
* @var bool
*/
public $exportedNameInExportAll = true;
/**
* Import.meta
*
* @var bool
*/
public $importMeta = true;
/**
* Coalescing operator
*
* @var bool
*/
public $coalescingOperator = true;
/**
* Optional chaining
*
* @var bool
*/
public $optionalChaining = true;
}

View File

@@ -0,0 +1,34 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\ES2021;
/**
* ES2021 features class
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*
* @codeCoverageIgnore
*/
class Features extends \Peast\Syntax\ES2020\Features
{
/**
* Logical assignment operators
*
* @var bool
*/
public $logicalAssignmentOperators = true;
/**
* Numeric literal separator
*
* @var bool
*/
public $numericLiteralSeparator = true;
}

View File

@@ -0,0 +1,62 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\ES2022;
/**
* ES2022 features class
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*
* @codeCoverageIgnore
*/
class Features extends \Peast\Syntax\ES2021\Features
{
/**
* Private methods and fields
*
* @var bool
*/
public $privateMethodsAndFields = true;
/**
* Class fields
*
* @var bool
*/
public $classFields = true;
/**
* "in" operator for private fields
*
* @var bool
*/
public $classFieldsPrivateIn = true;
/**
* Top level await
*
* @var bool
*/
public $topLevelAwait = true;
/**
* Class static block
*
* @var bool
*/
public $classStaticBlock = true;
/**
* Arbitrary module namespace identifier names
*
* @var bool
*/
public $arbitraryModuleNSNames = true;
}

View File

@@ -0,0 +1,27 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\ES2023;
/**
* ES2023 features class
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*
* @codeCoverageIgnore
*/
class Features extends \Peast\Syntax\ES2022\Features
{
/**
* Hashbang comments
*
* @var bool
*/
public $hashbangComments = true;
}

View File

@@ -0,0 +1,21 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\ES2024;
/**
* ES2024 features class
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*
* @codeCoverageIgnore
*/
class Features extends \Peast\Syntax\ES2023\Features
{
}

View File

@@ -0,0 +1,22 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax;
/**
* Encoding exception class. Encoding errors while scanning the source are
* thrown using this using this exception class.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*
* @codeCoverageIgnore
*/
class EncodingException extends \Exception
{
}

View File

@@ -0,0 +1,62 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax;
/**
* Events emitter class. An instance of this class is used by Parser and Scanner
* to emit events and attach listeners to them
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class EventsEmitter
{
/**
* Events registry array
*
* @var array
*/
protected $eventsRegistry = array();
/**
* Attaches a listener function to the given event
*
* @param string $event Event name
* @param callable $listener Listener function
*
* @return $this
*/
public function addListener($event, $listener)
{
if (!isset($this->eventsRegistry[$event])) {
$this->eventsRegistry[$event] = array();
}
$this->eventsRegistry[$event][] = $listener;
return $this;
}
/**
* Fires an event
*
* @param string $event Event name
* @param array $args Arguments to pass to functions attached to the
* event
*
* @return $this
*/
public function fire($event, $args = array())
{
if (isset($this->eventsRegistry[$event])) {
foreach ($this->eventsRegistry[$event] as $listener) {
call_user_func_array($listener, $args);
}
}
return $this;
}
}

View File

@@ -0,0 +1,50 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax;
/**
* Syntax exception class. Syntax errors in the source are thrown using this
* using this exception class.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*
* @codeCoverageIgnore
*/
class Exception extends \Exception
{
/**
* Error position
*
* @var Position
*/
protected $position;
/**
* Class constructor
*
* @param string $message Error message
* @param Position $position Error position
*/
public function __construct($message, Position $position)
{
parent::__construct($message);
$this->position = $position;
}
/**
* Returns the error position
*
* @return Position
*/
public function getPosition()
{
return $this->position;
}
}

View File

@@ -0,0 +1,188 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax;
/**
* Parser features class
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*
* @codeCoverageIgnore
*/
class Features
{
/**
* Exponentiation operator
*
* @var bool
*/
public $exponentiationOperator = false;
/**
* Async/await
*
* @var bool
*/
public $asyncAwait = false;
/**
* Trailing comma in function calls and declarations
*
* @var bool
*/
public $trailingCommaFunctionCallDeclaration = false;
/**
* For-in initializer
*
* @var bool
*/
public $forInInitializer = false;
/**
* Async iteration and generators
*
* @var bool
*/
public $asyncIterationGenerators = false;
/**
* Rest/spread properties
*
* @var bool
*/
public $restSpreadProperties = false;
/**
* Skip escape sequences checks in tagged template
*
* @var bool
*/
public $skipEscapeSeqCheckInTaggedTemplates = false;
/**
* Optional catch binding
*
* @var bool
*/
public $optionalCatchBinding = false;
/**
* Paragraph and line separator in strings
*
* @var bool
*/
public $paragraphLineSepInStrings = false;
/**
* Dynamic import
*
* @var bool
*/
public $dynamicImport = false;
/**
* BigInt literals
*
* @var bool
*/
public $bigInt = false;
/**
* Exported name for export all declarations
*
* @var bool
*/
public $exportedNameInExportAll = false;
/**
* Import.meta
*
* @var bool
*/
public $importMeta = false;
/**
* Coalescing operator
*
* @var bool
*/
public $coalescingOperator = false;
/**
* Optional chaining
*
* @var bool
*/
public $optionalChaining = false;
/**
* Logical assignment operators
*
* @var bool
*/
public $logicalAssignmentOperators = false;
/**
* Numeric literal separator
*
* @var bool
*/
public $numericLiteralSeparator = false;
/**
* Private methods and fields
*
* @var bool
*/
public $privateMethodsAndFields = false;
/**
* Class fields
*
* @var bool
*/
public $classFields = false;
/**
* "in" operator for private fields
*
* @var bool
*/
public $classFieldsPrivateIn = false;
/**
* Top level await
*
* @var bool
*/
public $topLevelAwait = false;
/**
* Class static block
*
* @var bool
*/
public $classStaticBlock = false;
/**
* Arbitrary module namespace identifier names
*
* @var bool
*/
public $arbitraryModuleNSNames = false;
/**
* Hashbang comments
*
* @var bool
*/
public $hashbangComments = false;
}

View File

@@ -0,0 +1,438 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\JSX;
use Peast\Syntax\Token;
/**
* JSX parser trait
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
trait Parser
{
/**
* Creates a JSX node
*
* @param string $nodeType Node's type
* @param mixed $position Node's start position
*
* @return \Peast\Syntax\Node\Node
*/
protected function createJSXNode($nodeType, $position)
{
return $this->createNode("JSX\\$nodeType", $position);
}
/**
* Parses a jsx fragment
*
* @return \Peast\Syntax\Node\JSX\JSXFragment|null
*/
protected function parseJSXFragment()
{
$startOpeningToken = $this->scanner->getToken();
if (!$startOpeningToken || $startOpeningToken->value !== "<") {
return null;
}
$endOpeningToken = $this->scanner->getNextToken();
if (!$endOpeningToken || $endOpeningToken->value !== ">") {
return null;
}
$this->scanner->consumeToken();
$this->scanner->consumeToken();
$children = $this->parseJSXChildren();
if (!($startClosingToken = $this->scanner->consume("<")) ||
!$this->scanner->consume("/") ||
!$this->scanner->reconsumeCurrentTokenInJSXMode() ||
$endOpeningToken->value !== ">") {
$this->error();
}
$this->scanner->consumeToken();
//Opening tag
$openingNode = $this->createJSXNode(
"JSXOpeningFragment",
$startOpeningToken
);
$this->completeNode(
$openingNode,
$endOpeningToken->location->end
);
//Closing tag
$closingNode = $this->createJSXNode(
"JSXClosingFragment",
$startClosingToken
);
$this->completeNode($closingNode);
//Fragment
$node = $this->createJSXNode("JSXFragment", $startOpeningToken);
$node->setOpeningFragment($openingNode);
$node->setClosingFragment($closingNode);
if ($children) {
$node->setChildren($children);
}
return $this->completeNode($node);
}
/**
* Parses a group of jsx children
*
* @return \Peast\Syntax\Node\Node[]|null
*/
protected function parseJSXChildren()
{
$children = array();
while ($child = $this->parseJSXChild()) {
$children[] = $child;
}
return count($children) ? $children : null;
}
/**
* Parses a jsx child
*
* @return \Peast\Syntax\Node\Node|null
*/
protected function parseJSXChild()
{
if ($node = $this->parseJSXText()) {
return $node;
} elseif ($node = $this->parseJSXFragment()) {
return $node;
} elseif($node = $this->parseJSXElement()) {
return $node;
} elseif ($startToken = $this->scanner->consume("{")) {
$spread = $this->scanner->consume("...");
$exp = $this->parseAssignmentExpression();
$midPos = $this->scanner->getPosition();
if (($spread && !$exp) || !$this->scanner->consume("}")) {
$this->error();
}
$node = $this->createJSXNode(
$spread ? "JSXSpreadChild" : "JSXExpressionContainer",
$startToken
);
if (!$exp) {
$exp = $this->createJSXNode("JSXEmptyExpression", $midPos);
$this->completeNode($exp, $midPos);
}
$node->setExpression($exp);
return $this->completeNode($node);
}
return null;
}
/**
* Parses a jsx text
*
* @return \Peast\Syntax\Node\JSX\JSXText|null
*/
protected function parseJSXText()
{
if (!($token = $this->scanner->reconsumeCurrentTokenAsJSXText())) {
return null;
}
$this->scanner->consumeToken();
$node = $this->createJSXNode("JSXText", $token);
$node->setRaw($token->value);
return $this->completeNode($node, $token->location->end);
}
/**
* Parses a jsx element
*
* @return \Peast\Syntax\Node\JSX\JSXElement|null
*/
protected function parseJSXElement()
{
$startOpeningToken = $this->scanner->getToken();
if (!$startOpeningToken || $startOpeningToken->value !== "<") {
return null;
}
$nextToken = $this->scanner->getNextToken();
if ($nextToken && $nextToken->value === "/") {
return null;
}
$this->scanner->consumeToken();
if (!($name = $this->parseJSXIdentifierOrMemberExpression())) {
$this->error();
}
$attributes = $this->parseJSXAttributes();
$selfClosing = $this->scanner->consume("/");
$endOpeningToken = $this->scanner->reconsumeCurrentTokenInJSXMode();
if (!$endOpeningToken || $endOpeningToken->value !== ">") {
$this->error();
}
$this->scanner->consumeToken();
if (!$selfClosing) {
$children = $this->parseJSXChildren();
if (
($startClosingToken = $this->scanner->consume("<")) &&
$this->scanner->consume("/") &&
($closingName = $this->parseJSXIdentifierOrMemberExpression()) &&
($endClosingToken = $this->scanner->reconsumeCurrentTokenInJSXMode()) &&
($endClosingToken->value === ">")
) {
$this->scanner->consumeToken();
if (!$this->isSameJSXElementName($name, $closingName)) {
$this->error("Closing tag does not match opening tag");
}
} else {
$this->error();
}
}
//Opening tag
$openingNode = $this->createJSXNode(
"JSXOpeningElement",
$startOpeningToken
);
$openingNode->setName($name);
$openingNode->setSelfClosing($selfClosing);
if ($attributes) {
$openingNode->setAttributes($attributes);
}
$this->completeNode(
$openingNode,
$endOpeningToken->location->end
);
//Closing tag
$closingNode = null;
if (!$selfClosing) {
$closingNode = $this->createJSXNode(
"JSXClosingElement",
$startClosingToken
);
$closingNode->setName($closingName);
$this->completeNode($closingNode);
}
//Element
$node = $this->createJSXNode("JSXElement", $startOpeningToken);
$node->setOpeningElement($openingNode);
if ($closingNode) {
$node->setClosingElement($closingNode);
if ($children) {
$node->setChildren($children);
}
}
return $this->completeNode($node);
}
/**
* Parses a jsx identifier, namespaced identifier or member expression
*
* @param bool $allowMember True to allow member expressions
*
* @return \Peast\Syntax\Node\Node|null
*/
protected function parseJSXIdentifierOrMemberExpression($allowMember = true)
{
$idToken = $this->scanner->reconsumeCurrentTokenInJSXMode();
if (!$idToken || $idToken->type !== Token::TYPE_JSX_IDENTIFIER) {
return null;
}
$this->scanner->consumeToken();
$idNode = $this->createJSXNode("JSXIdentifier", $idToken);
$idNode->setName($idToken->value);
$idNode = $this->completeNode($idNode);
//Namespaced identifier
if ($this->scanner->consume(":")) {
$idToken2 = $this->scanner->reconsumeCurrentTokenInJSXMode();
if (!$idToken2 || $idToken2->type !== Token::TYPE_JSX_IDENTIFIER) {
$this->error();
}
$this->scanner->consumeToken();
$idNode2 = $this->createJSXNode("JSXIdentifier", $idToken2);
$idNode2->setName($idToken2->value);
$idNode2 = $this->completeNode($idNode2);
$node = $this->createJSXNode("JSXNamespacedName", $idToken);
$node->setNamespace($idNode);
$node->setName($idNode2);
return $this->completeNode($node);
}
//Get following identifiers
$nextIds = array();
if ($allowMember) {
while ($this->scanner->consume(".")) {
$nextId = $this->scanner->reconsumeCurrentTokenInJSXMode();
if (!$nextId || $nextId->type !== Token::TYPE_JSX_IDENTIFIER) {
$this->error();
}
$this->scanner->consumeToken();
$nextIds[] = $nextId;
}
}
//Create the member expression if required
$objectNode = $idNode;
foreach ($nextIds as $nid) {
$propEnd = $nid->location->end;
$propNode = $this->createJSXNode("JSXIdentifier", $nid);
$propNode->setName($nid->value);
$propNode = $this->completeNode($propNode, $propEnd);
$node = $this->createJSXNode("JSXMemberExpression", $objectNode);
$node->setObject($objectNode);
$node->setProperty($propNode);
$objectNode = $this->completeNode($node, $propEnd);
}
return $objectNode;
}
/**
* Parses a jsx attributes list
*
* @return \Peast\Syntax\Node\Node[]|null
*/
protected function parseJSXAttributes()
{
$attributes = array();
while (
($attr = $this->parseJSXSpreadAttribute()) ||
($attr = $this->parseJSXAttribute())
) {
$attributes[] = $attr;
}
return count($attributes) ? $attributes : null;
}
/**
* Parses a jsx spread attribute
*
* @return \Peast\Syntax\Node\JSX\JSXSpreadAttribute|null
*/
protected function parseJSXSpreadAttribute()
{
if (!($openToken = $this->scanner->consume("{"))) {
return null;
}
if (
$this->scanner->consume("...") &&
($exp = $this->parseAssignmentExpression()) &&
$this->scanner->consume("}")
) {
$node = $this->createJSXNode("JSXSpreadAttribute", $openToken);
$node->setArgument($exp);
return $this->completeNode($node);
}
$this->error();
}
/**
* Parses a jsx spread attribute
*
* @return \Peast\Syntax\Node\JSX\JSXSpreadAttribute|null
*/
protected function parseJSXAttribute()
{
if (!($name = $this->parseJSXIdentifierOrMemberExpression(false))) {
return null;
}
$value = null;
if ($this->scanner->consume("=")) {
$strToken = $this->scanner->reconsumeCurrentTokenInJSXMode();
if ($strToken && $strToken->type === Token::TYPE_STRING_LITERAL) {
$this->scanner->consumeToken();
$value = $this->createNode("StringLiteral", $strToken);
$value->setRaw($strToken->value);
$value = $this->completeNode($value);
} elseif ($startExp = $this->scanner->consume("{")) {
if (
($exp = $this->parseAssignmentExpression()) &&
$this->scanner->consume("}")
) {
$value = $this->createJSXNode(
"JSXExpressionContainer",
$startExp
);
$value->setExpression($exp);
$value = $this->completeNode($value);
} else {
$this->error();
}
} elseif (
!($value = $this->parseJSXFragment()) &&
!($value = $this->parseJSXElement())
) {
$this->error();
}
}
$node = $this->createJSXNode("JSXAttribute", $name);
$node->setName($name);
if ($value) {
$node->setValue($value);
}
return $this->completeNode($node);
}
/**
* Checks that 2 tag names are equal
*
* @param \Peast\Syntax\Node\Node $n1 First name
* @param \Peast\Syntax\Node\Node $n2 Second name
*
* @return bool
*/
protected function isSameJSXElementName($n1, $n2)
{
$type = $n1->getType();
if ($type !== $n2->getType()) {
return false;
} elseif ($type === "JSXNamespacedName") {
return $this->isSameJSXElementName(
$n1->getNamespace(), $n2->getNamespace()
) && $this->isSameJSXElementName(
$n1->getName(), $n2->getName()
);
} elseif ($type === "JSXMemberExpression") {
return $this->isSameJSXElementName(
$n1->getObject(), $n2->getObject()
) && $this->isSameJSXElementName(
$n1->getProperty(), $n2->getProperty()
);
}
return $type === "JSXIdentifier" && $n1->getName() === $n2->getName();
}
}

View File

@@ -0,0 +1,123 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\JSX;
use Peast\Syntax\Token;
/**
* JSX scanner trait
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
trait Scanner
{
/**
* Tries to reconsume the current token as a jsx text if possible
*
* @return Token|null
*/
public function reconsumeCurrentTokenAsJSXText()
{
//Current and next tokens must be reset and the open brackets count must be correct
//like they were never scanned
foreach (array($this->currentToken, $this->nextToken) as $token) {
if ($token && isset($this->brackets[$token->value])) {
if ($refBracket = $this->brackets[$token->value]) {
$this->openBrackets[$refBracket]++;
} else {
$this->openBrackets[$token->value]--;
}
}
}
$this->nextToken = null;
$this->currentToken = null;
$startPosition = $this->getPosition();
$this->setScanPosition($startPosition);
$result = $this->consumeUntil(array("{", "<"), false, false);
if ($result) {
$this->currentToken = new Token(Token::TYPE_JSX_TEXT, $result[0]);
$this->currentToken->location->start = $startPosition;
$this->currentToken->location->end = $this->getPosition(true);
}
return $this->currentToken;
}
/**
* Reconsumes the current token in jsx mode
*
* @return Token|null
*/
public function reconsumeCurrentTokenInJSXMode()
{
$this->jsx = true;
$this->nextToken = null;
$this->currentToken = null;
$startPosition = $this->getPosition();
$this->setScanPosition($startPosition);
$token = $this->getToken();
$this->jsx = false;
return $token;
}
/**
* String scanning method in jsx mode
*
* @return Token|null
*/
public function scanJSXString()
{
return $this->scanString(false);
}
/**
* String punctuator method in jsx mode
*
* @return Token|null
*/
public function scanJSXPunctuator()
{
//The ">" character in jsx mode must be emitted in its own token
//without matching longer sequences like ">>"
$char = $this->charAt();
if ($char === ">") {
$this->index++;
$this->column++;
return new Token(Token::TYPE_PUNCTUATOR, $char);
}
return $this->scanPunctuator();
}
/**
* Identifier scanning method in jsx mode
*
* @return Token|null
*/
public function scanJSXIdentifier()
{
$buffer = "";
$char = $this->charAt();
if ($char !== null && $this->isIdentifierChar($char)) {
do {
$buffer .= $char;
$this->index++;
$this->column++;
$char = $this->charAt();
} while (
$char !== null &&
($this->isIdentifierChar($char, false) || $char === "-")
);
}
return $buffer === "" ? null : new Token(Token::TYPE_JSX_IDENTIFIER, $buffer);
}
}

153
vendor/mck89/peast/lib/Peast/Syntax/LSM.php vendored Executable file
View File

@@ -0,0 +1,153 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax;
/**
* Longest Sequence Matcher. Utility class used by the scanner to consume
* the longest sequence of character given a set of allowed characters sequences.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class LSM
{
/**
* Internal sequences map
*
* @var array
*/
protected $map = array();
/**
* Encoding handle flag
*
* @var bool
*/
protected $handleEncoding = false;
/**
* Class constructor
*
* @param array $sequences Allowed characters sequences
* @param bool $handleEncoding True to handle encoding when matching
*/
function __construct($sequences, $handleEncoding = false)
{
$this->handleEncoding = $handleEncoding;
foreach ($sequences as $s) {
$this->add($s);
}
}
/**
* Adds a sequence
*
* @param string $sequence Sequence to add
*
* @return $this
*/
public function add($sequence)
{
if ($this->handleEncoding) {
$s = Utils::stringToUTF8Array($sequence);
$first = $s[0];
$len = count($s);
} else {
$first = $sequence[0];
$len = strlen($sequence);
}
if (!isset($this->map[$first])) {
$this->map[$first] = array(
"maxLen" => $len,
"map" => array($sequence)
);
} else {
$this->map[$first]["map"][] = $sequence;
$this->map[$first]["maxLen"] = max($this->map[$first]["maxLen"], $len);
}
return $this;
}
/**
* Removes a sequence
*
* @param string $sequence Sequence to remove
*
* @return $this
*/
public function remove($sequence)
{
if ($this->handleEncoding) {
$s = Utils::stringToUTF8Array($sequence);
$first = $s[0];
} else {
$first = $sequence[0];
}
if (isset($this->map[$first])) {
$len = $this->handleEncoding ? count($s) : strlen($sequence);
$this->map[$first]["map"] = array_diff(
$this->map[$first]["map"], array($sequence)
);
if (!count($this->map[$first]["map"])) {
unset($this->map[$first]);
} elseif ($this->map[$first]["maxLen"] === $len) {
// Recalculate the max length if necessary
foreach ($this->map[$first]["map"] as $m) {
$this->map[$first]["maxLen"] = max(
$this->map[$first]["maxLen"],
strlen($m)
);
}
}
}
return $this;
}
/**
* Executes the match. It returns an array where the first element is the
* number of consumed characters and the second element is the match. If
* no match is found it returns null.
*
* @param Scanner $scanner Scanner instance
* @param int $index Current index
* @param string $char Current character
*
* @return array|null
*/
public function match($scanner, $index, $char)
{
$consumed = 1;
$bestMatch = null;
if (isset($this->map[$char])) {
//If the character is present in the map and it has a max length of
//1, match immediately
if ($this->map[$char]["maxLen"] === 1) {
$bestMatch = array($consumed, $char);
} else {
//Otherwise consume a number of characters equal to the max
//length and find the longest match
$buffer = $char;
$map = $this->map[$char]["map"];
$maxLen = $this->map[$char]["maxLen"];
do {
if (in_array($buffer, $map)) {
$bestMatch = array($consumed, $buffer);
}
$nextChar = $scanner->charAt($index + $consumed);
if ($nextChar === null) {
break;
}
$buffer .= $nextChar;
$consumed++;
} while ($consumed <= $maxLen);
}
}
return $bestMatch;
}
}

View File

@@ -0,0 +1,63 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents an array literal.
* For example: [a, b, c]
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ArrayExpression extends Node implements Expression
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"elements" => true
);
/**
* Array elements
*
* @var Expression[]|SpreadElement[]
*/
protected $elements = array();
/**
* Returns array elements
*
* @return Expression[]|SpreadElement[]
*/
public function getElements()
{
return $this->elements;
}
/**
* Sets array elements
*
* @param Expression[]|SpreadElement[] $elements Array elements to set
*
* @return $this
*/
public function setElements($elements)
{
$this->assertArrayOf(
$elements,
array("Expression", "SpreadElement"),
true
);
$this->elements = $elements;
return $this;
}
}

View File

@@ -0,0 +1,59 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents an array binding pattern.
* For example: [a, b, c] = d
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ArrayPattern extends Node implements Pattern
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"elements" => true
);
/**
* Array elements
*
* @var Pattern[]
*/
protected $elements = array();
/**
* Returns array elements
*
* @return Pattern[]
*/
public function getElements()
{
return $this->elements;
}
/**
* Sets array elements
*
* @param Pattern[] $elements Array elements to set
*
* @return $this
*/
public function setElements($elements)
{
$this->assertArrayOf($elements, "Pattern", true);
$this->elements = $elements;
return $this;
}
}

View File

@@ -0,0 +1,72 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents an arrow function.
* For example: var fn = (a, b) => console.log(a, b)
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ArrowFunctionExpression extends Function_ implements Expression
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"expression" => false
);
/**
* This flag is true when function body is wrapped in curly braces
*
* @var bool
*/
protected $expression = false;
/**
* Sets the function body
*
* @param BlockStatement|Expression $body Function body
*
* @return $this
*/
public function setBody($body)
{
$this->assertType($body, array("BlockStatement", "Expression"));
$this->body = $body;
return $this;
}
/**
* Returns the expression flag
*
* @return bool
*/
public function getExpression()
{
return $this->expression;
}
/**
* Sets the expression flag
*
* @param bool $expression Expression flag
*
* @return $this
*/
public function setExpression($expression)
{
$this->expression = (bool) $expression;
return $this;
}
}

View File

@@ -0,0 +1,121 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents an assignment expression.
* For example: a = b
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class AssignmentExpression extends Node implements Expression
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"left" => true,
"operator" => false,
"right" => true
);
/**
* The assignment operator
*
* @var string
*/
protected $operator;
/**
* The left node of the assignment
*
* @var Pattern|Expression
*/
protected $left;
/**
* The right node of the assignment
*
* @var Expression
*/
protected $right;
/**
* Returns the assignment operator
*
* @return string
*/
public function getOperator()
{
return $this->operator;
}
/**
* Sets the assignment operator
*
* @param string $operator Assignment operator
*
* @return $this
*/
public function setOperator($operator)
{
$this->operator = $operator;
return $this;
}
/**
* Returns the left node of the assignment
*
* @return Pattern|Expression
*/
public function getLeft()
{
return $this->left;
}
/**
* Sets the left node of the assignment
*
* @param Pattern|Expression $left The node to set
*
* @return $this
*/
public function setLeft($left)
{
$this->assertType($left, array("Pattern", "Expression"));
$this->left = $left;
return $this;
}
/**
* Returns the right node of the assignment
*
* @return Expression
*/
public function getRight()
{
return $this->right;
}
/**
* Sets the right node of the assignment
*
* @param Expression $right The node to set
*
* @return $this
*/
public function setRight(Expression $right)
{
$this->right = $right;
return $this;
}
}

View File

@@ -0,0 +1,89 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents an assignment in a binding context.
* For example "a = b" in: var {a = b} = c
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class AssignmentPattern extends Node implements Pattern
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"left" => true,
"right" => true
);
/**
* The left node of the assignment
*
* @var Pattern
*/
protected $left;
/**
* The right node of the assignment
*
* @var Expression
*/
protected $right;
/**
* Returns the left node of the assignment
*
* @return Pattern
*/
public function getLeft()
{
return $this->left;
}
/**
* Sets the left node of the assignment
*
* @param Pattern $left Left node
*
* @return $this
*/
public function setLeft(Pattern $left)
{
$this->left = $left;
return $this;
}
/**
* Returns the right node of the assignment
*
* @return Expression
*/
public function getRight()
{
return $this->right;
}
/**
* Sets the right node of the assignment
*
* @param Expression $right Right node
*
* @return $this
*/
public function setRight(Expression $right)
{
$this->right = $right;
return $this;
}
}

View File

@@ -0,0 +1,71 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a property in an object binding pattern.
* For example "a" in: var {a} = b
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class AssignmentProperty extends Property
{
/**
* Returns node's type
*
* @return string
*/
public function getType()
{
return "Property";
}
/**
* Sets the property value
*
* @param Pattern $value Property value
*
* @return $this
*/
public function setValue($value)
{
$this->assertType($value, "Pattern");
$this->value = $value;
return $this;
}
/**
* Sets the property kind that is one of the kind constants
*
* @param string $kind Property kind
*
* @return $this
*
* @codeCoverageIgnore
*/
public function setKind($kind)
{
return $this;
}
/**
* Sets the property method flag that is true when the property is a method
*
* @param bool $method Method flag
*
* @return $this
*
* @codeCoverageIgnore
*/
public function setMethod($method)
{
return $this;
}
}

View File

@@ -0,0 +1,57 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents an await expression.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class AwaitExpression extends Node implements Expression
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"argument" => true
);
/**
* Expression's argument
*
* @var Expression
*/
protected $argument;
/**
* Returns the expression's argument
*
* @return Expression
*/
public function getArgument()
{
return $this->argument;
}
/**
* Sets the expression's argument
*
* @param Expression $argument Argument
*
* @return $this
*/
public function setArgument(Expression $argument)
{
$this->argument = $argument;
return $this;
}
}

View File

@@ -0,0 +1,70 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a BigInt literal.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class BigIntLiteral extends Literal
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"bigint" => false
);
/**
* Node's value
*
* @var mixed
*/
protected $bigint;
/**
* Sets node's value
*
* @param float $value Value
*
* @return $this
*/
public function setValue($value)
{
//Value, Raw and Bigint are always the same value
$this->value = $this->raw = $this->bigint = $value;
return $this;
}
/**
* Returns node's value
*
* @return string
*/
public function getBigint()
{
return $this->bigint;
}
/**
* Sets node's value
*
* @param string $bigint Value
*
* @return $this
*/
public function setBigint($bigint)
{
return $this->setValue($bigint);
}
}

View File

@@ -0,0 +1,121 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a binary expression.
* For example: a + b
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class BinaryExpression extends Node implements Expression
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"left" => true,
"operator" => false,
"right" => true
);
/**
* Operator
*
* @var string
*/
protected $operator;
/**
* Left expression
*
* @var Expression|PrivateIdentifier
*/
protected $left;
/**
* Right expression
*
* @var Expression
*/
protected $right;
/**
* Returns the operator
*
* @return string
*/
public function getOperator()
{
return $this->operator;
}
/**
* Sets the operator
*
* @param string $operator Operator
*
* @return $this
*/
public function setOperator($operator)
{
$this->operator = $operator;
return $this;
}
/**
* Returns the left expression
*
* @return Expression|PrivateIdentifier
*/
public function getLeft()
{
return $this->left;
}
/**
* Sets the left expression
*
* @param Expression|PrivateIdentifier $left Left expression
*
* @return $this
*/
public function setLeft($left)
{
$this->assertType($left, array("Expression", "PrivateIdentifier"));
$this->left = $left;
return $this;
}
/**
* Returns the right expression
*
* @return Expression
*/
public function getRight()
{
return $this->right;
}
/**
* Sets the right expression
*
* @param Expression $right Right expression
*
* @return $this
*/
public function setRight(Expression $right)
{
$this->right = $right;
return $this;
}
}

View File

@@ -0,0 +1,59 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a block of code wrapped in curly braces.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class BlockStatement extends Node implements Statement
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"body" => true
);
/**
* Block's body
*
* @var Statement[]
*/
protected $body = array();
/**
* Returns block's body
*
* @return Statement[]
*/
public function getBody()
{
return $this->body;
}
/**
* Sets block's body
*
* @param Statement[] $body Array of Statements that are the body of the
* block
*
* @return $this
*/
public function setBody($body)
{
$this->assertArrayOf($body, "Statement");
$this->body = $body;
return $this;
}
}

View File

@@ -0,0 +1,38 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a boolean literal.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class BooleanLiteral extends Literal
{
/**
* Sets node's value
*
* @param mixed $value Value
*
* @return $this
*/
public function setValue($value)
{
if ($value === "true") {
$this->value = true;
} elseif ($value === "false") {
$this->value = false;
} else {
$this->value = (bool) $value;
}
$this->raw = $this->value ? "true" : "false";
return $this;
}
}

View File

@@ -0,0 +1,58 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents the "break" statement inside loops.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class BreakStatement extends Node implements Statement
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"label" => true
);
/**
* The optional label of the break statement
*
* @var Identifier
*/
protected $label;
/**
* Returns the node's label
*
* @return Identifier
*/
public function getLabel()
{
return $this->label;
}
/**
* Sets the node's label
*
* @param Identifier $label Node's label
*
* @return $this
*/
public function setLabel($label)
{
$this->assertType($label, "Identifier", true);
$this->label = $label;
return $this;
}
}

View File

@@ -0,0 +1,91 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a call expression.
* For example: test()
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class CallExpression extends ChainElement
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"callee" => true,
"arguments" => true
);
/**
* The callee expression
*
* @var Expression|Super
*/
protected $callee;
/**
* The arguments array
*
* @var Expression[]|SpreadElement[]
*/
protected $arguments = array();
/**
* Returns the callee expression
*
* @return Expression|Super
*/
public function getCallee()
{
return $this->callee;
}
/**
* Sets the callee expression
*
* @param Expression|Super $callee Callee expression
*
* @return $this
*/
public function setCallee($callee)
{
$this->assertType($callee, array("Expression", "Super"));
$this->callee = $callee;
return $this;
}
/**
* Returns the arguments array
*
* @return Expression[]|SpreadElement[]
*/
public function getArguments()
{
return $this->arguments;
}
/**
* Sets the arguments array
*
* @param Expression[]|SpreadElement[] $arguments Arguments array
*
* @return $this
*/
public function setArguments($arguments)
{
$this->assertArrayOf($arguments, array("Expression", "SpreadElement"));
$this->arguments = $arguments;
return $this;
}
}

View File

@@ -0,0 +1,89 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents the catch clause in a try-catch statement.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class CatchClause extends Node
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"param" => true,
"body" => true
);
/**
* The catch clause parameter
*
* @var Pattern
*/
protected $param;
/**
* The body of the catch clause
*
* @var BlockStatement
*/
protected $body;
/**
* Returns the catch clause parameter
*
* @return Pattern
*/
public function getParam()
{
return $this->param;
}
/**
* Sets the catch clause parameter
*
* @param Pattern $param Catch clause parameter
*
* @return $this
*/
public function setParam($param)
{
$this->assertType($param, "Pattern", true);
$this->param = $param;
return $this;
}
/**
* Returns the body of the catch clause
*
* @return BlockStatement
*/
public function getBody()
{
return $this->body;
}
/**
* Sets the body of the catch clause
*
* @param BlockStatement $body The block of code inside the catch clause
*
* @return $this
*/
public function setBody(BlockStatement $body)
{
$this->body = $body;
return $this;
}
}

View File

@@ -0,0 +1,55 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a chain element.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
abstract class ChainElement extends Node implements Expression
{
protected $propertiesMap = array(
"optional" => false
);
/**
* Optional flag that is true if the node is in the optional
* part of a chain expression
*
* @var bool
*/
protected $optional = false;
/**
* Returns the optional flag that is true if the node is in
* the optional part of a chain expression
*
* @return bool
*/
public function getOptional()
{
return $this->optional;
}
/**
* Sets the optional flag that is true if the node is in
* the optional part of a chain expression
*
* @param bool $optional Optional flag
*
* @return $this
*/
public function setOptional($optional)
{
$this->optional = (bool) $optional;
return $this;
}
}

View File

@@ -0,0 +1,58 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a chain expression.
* For example: test?.test?.()
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ChainExpression extends Node implements Expression
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"expression" => true
);
/**
* The wrapped expression
*
* @var Expression
*/
protected $expression;
/**
* Returns the wrapped expression
*
* @return Expression
*/
public function getExpression()
{
return $this->expression;
}
/**
* Sets the wrapped expression
*
* @param Expression $expression Wrapped expression
*
* @return $this
*/
public function setExpression(Expression $expression)
{
$this->expression = $expression;
return $this;
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a class body.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ClassBody extends Node
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"body" => true
);
/**
* Class methods and properties
*
* @var MethodDefinition[]|PropertyDefinition[]|StaticBlock[]
*/
protected $body = array();
/**
* Returns class methods and properties
*
* @return MethodDefinition[]|PropertyDefinition[]|StaticBlock[]
*/
public function getBody()
{
return $this->body;
}
/**
* Sets class methods and properties
*
* @param MethodDefinition[]|PropertyDefinition[]|StaticBlock[] $body Class methods array
*
* @return $this
*/
public function setBody($body)
{
$this->assertArrayOf(
$body,
array("MethodDefinition", "PropertyDefinition", "StaticBlock")
);
$this->body = $body;
return $this;
}
}

View File

@@ -0,0 +1,33 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a class declaration.
* For example: class test {}
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ClassDeclaration extends Class_ implements Declaration
{
/**
* Sets the class identifier
*
* @param Identifier $id Class identifier
*
* @return $this
*/
public function setId($id)
{
$this->assertType($id, "Identifier");
$this->id = $id;
return $this;
}
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a class expression
* For example: test = class {}
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ClassExpression extends Class_ implements Expression
{
}

View File

@@ -0,0 +1,122 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* Abstract class for classes.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
abstract class Class_ extends Node
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"id" => true,
"superClass" => true,
"body" => true
);
/**
* Class name
*
* @var Identifier
*/
protected $id;
/**
* Extended class
*
* @var Expression
*/
protected $superClass;
/**
* Class body
*
* @var ClassBody
*/
protected $body;
/**
* Returns class name
*
* @return Identifier
*/
public function getId()
{
return $this->id;
}
/**
* Sets class name
*
* @param Identifier $id Class name
*
* @return $this
*/
public function setId($id)
{
$this->assertType($id, "Identifier", true);
$this->id = $id;
return $this;
}
/**
* Returns extended class
*
* @return Expression
*/
public function getSuperClass()
{
return $this->superClass;
}
/**
* Sets extended class
*
* @param Expression $superClass Extended class
*
* @return $this
*/
public function setSuperClass($superClass)
{
$this->assertType($superClass, "Expression", true);
$this->superClass = $superClass;
return $this;
}
/**
* Returns class body
*
* @return ClassBody
*/
public function getBody()
{
return $this->body;
}
/**
* Sets class body
*
* @param ClassBody $body Class body
*
* @return $this
*/
public function setBody($body)
{
$this->assertType($body, "ClassBody");
$this->body = $body;
return $this;
}
}

View File

@@ -0,0 +1,215 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a comment.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class Comment extends Node
{
//Comment kind constants
/**
* Inline comment
*/
const KIND_INLINE = "inline";
/**
* Multiline comment
*/
const KIND_MULTILINE = "multiline";
/**
* Html open comment
*/
const KIND_HTML_OPEN = "html-open";
/**
* Html close comment
*/
const KIND_HTML_CLOSE = "html-close";
/**
* Hashbang comment
*/
const KIND_HASHBANG = "hashbang";
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"kind" => false,
"text" => false
);
/**
* The comment kind
*
* @var string
*/
protected $kind;
/**
* The comment text
*
* @var string
*/
protected $text;
/**
* Returns the comment kind
*
* @return string
*/
public function getKind()
{
return $this->kind;
}
/**
* Sets the comment kind
*
* @param string $kind Comment kind
*
* @return $this
*/
public function setKind($kind)
{
$this->kind = $kind;
return $this;
}
/**
* Returns the comment text
*
* @return string
*/
public function getText()
{
return $this->text;
}
/**
* Sets the comment text
*
* @param string $text Comment text
*
* @return $this
*/
public function setText($text)
{
$this->text = $text;
return $this;
}
/**
* Returns the comment raw text
*
* @return string
*/
public function getRawText()
{
$text = $this->getText();
$kind = $this->getKind();
if ($kind === self::KIND_MULTILINE) {
$sanitize = "*/";
} else {
$sanitize = array("\n", "\r");
}
$text = str_replace($sanitize, "", $text);
if ($kind === self::KIND_INLINE) {
return "//" . $text;
} elseif ($kind === self::KIND_HASHBANG) {
return "#!" . $text;
} elseif ($kind === self::KIND_HTML_OPEN) {
return "<!--" . $text;
} elseif ($kind === self::KIND_HTML_CLOSE) {
return "-->" . $text;
} else {
return "/*" . $text . "*/";
}
}
/**
* Sets the comment raw text
*
* @param string $rawText Comment raw text
*
* @return $this
*/
public function setRawText($rawText)
{
$start = substr($rawText, 0, 2);
if ($start === "//") {
$kind = self::KIND_INLINE;
$text = substr($rawText, 2);
} elseif ($start === "/*" && substr($rawText, -2) === "*/") {
$kind = self::KIND_MULTILINE;
$text = substr($rawText, 2, -2);
} elseif ($start === "#!") {
$kind = self::KIND_HASHBANG;
$text = substr($rawText, 2);
} elseif ($start === "<!" && substr($rawText, 2, 2) === "--") {
$kind = self::KIND_HTML_OPEN;
$text = substr($rawText, 4);
} elseif ($start === "--" && substr($rawText, 2, 1) === ">") {
$kind = self::KIND_HTML_CLOSE;
$text = substr($rawText, 3);
} else {
throw new \Exception("Invalid comment");
}
return $this->setKind($kind)->setText($text);
}
/**
* Sets leading comments array
*
* @param Comment[] $comments Comments array
*
* @return $this
*/
public function setLeadingComments($comments)
{
//Comments cannot be attached to other comments
return $this;
}
/**
* Sets trailing comments array
*
* @param Comment[] $comments Comments array
*
* @return $this
*/
public function setTrailingComments($comments)
{
//Comments cannot be attached to other comments
return $this;
}
/**
* Returns a serializable version of the node
*
* @return array
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
$ret = parent::jsonSerialize();
unset($ret["leadingComments"]);
unset($ret["trailingComments"]);
return $ret;
}
}

View File

@@ -0,0 +1,120 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a conditional expression.
* For example: test() ? ok() : fail()
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ConditionalExpression extends Node implements Expression
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"test" => true,
"consequent" => true,
"alternate" => true
);
/**
* The test expression
*
* @var Expression
*/
protected $test;
/**
* The consequent expression
*
* @var Expression
*/
protected $consequent;
/**
* The alternate expression
*
* @var Expression
*/
protected $alternate;
/**
* Returns the test expression
*
* @return Expression
*/
public function getTest()
{
return $this->test;
}
/**
* Sets the test expression
*
* @param Expression $test Test expression
*
* @return $this
*/
public function setTest(Expression $test)
{
$this->test = $test;
return $this;
}
/**
* Returns the consequent expression
*
* @return Expression
*/
public function getConsequent()
{
return $this->consequent;
}
/**
* Sets the consequent expression
*
* @param Expression $consequent Consequent expression
*
* @return $this
*/
public function setConsequent(Expression $consequent)
{
$this->consequent = $consequent;
return $this;
}
/**
* Returns the alternate expression
*
* @return Expression
*/
public function getAlternate()
{
return $this->alternate;
}
/**
* Sets the alternate expression
*
* @param Expression $alternate Alternate expression
*
* @return $this
*/
public function setAlternate(Expression $alternate)
{
$this->alternate = $alternate;
return $this;
}
}

View File

@@ -0,0 +1,58 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents the "continue" statement inside loops.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ContinueStatement extends Node implements Statement
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"label" => true
);
/**
* The optional label of the continue statement
*
* @var Identifier
*/
protected $label;
/**
* Returns the node's label
*
* @return Identifier
*/
public function getLabel()
{
return $this->label;
}
/**
* Sets the node's label
*
* @param Identifier $label Node's label
*
* @return $this
*/
public function setLabel($label)
{
$this->assertType($label, "Identifier", true);
$this->label = $label;
return $this;
}
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a debugger statement.
* For example: debugger;
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class DebuggerStatement extends Node implements Statement
{
}

View File

@@ -0,0 +1,19 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* Interface that every declaration node must implement.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
interface Declaration extends Statement
{
}

View File

@@ -0,0 +1,89 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a do-while loop.
* For example: do {} while (test)
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class DoWhileStatement extends Node implements Statement
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"body" => true,
"test" => true
);
/**
* The loop body
*
* @var Statement
*/
protected $body;
/**
* The loop condition
*
* @var Expression
*/
protected $test;
/**
* Returns the loop body
*
* @return Statement
*/
public function getBody()
{
return $this->body;
}
/**
* Sets the loop body
*
* @param Statement $body Loop body
*
* @return $this
*/
public function setBody(Statement $body)
{
$this->body = $body;
return $this;
}
/**
* Returns the loop condition
*
* @return Expression
*/
public function getTest()
{
return $this->test;
}
/**
* Sets the loop condition
*
* @param Expression $test Loop
*
* @return $this
*/
public function setTest(Expression $test)
{
$this->test = $test;
return $this;
}
}

View File

@@ -0,0 +1,19 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents an empty statement (;).
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class EmptyStatement extends Node implements Statement
{
}

View File

@@ -0,0 +1,90 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents an "export all" declaration.
* For example: export * from "test"
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ExportAllDeclaration extends Node implements ModuleDeclaration
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"source" => true,
"exported" => true
);
/**
* The export source
*
* @var Literal
*/
protected $source;
/**
* The exported name
*
* @var Identifier|StringLiteral
*/
protected $exported;
/**
* Returns the export source
*
* @return Literal
*/
public function getSource()
{
return $this->source;
}
/**
* Sets the export source
*
* @param Literal $source Export source
*
* @return $this
*/
public function setSource(Literal $source)
{
$this->source = $source;
return $this;
}
/**
* Returns the exported name
*
* @return Identifier|StringLiteral
*/
public function getExported()
{
return $this->exported;
}
/**
* Sets the exported name
*W
* @param Identifier|StringLiteral $exported Exported name
*
* @return $this
*/
public function setExported($exported)
{
$this->assertType($exported, array("Identifier", "StringLiteral"), true);
$this->exported = $exported;
return $this;
}
}

View File

@@ -0,0 +1,59 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents the export default declaration.
* For example: export default a
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ExportDefaultDeclaration extends Node implements ModuleDeclaration
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"declaration" => true
);
/**
* The exported declaration
*
* @var Declaration|Expression
*/
protected $declaration;
/**
* Returns the exported declaration
*
* @return Declaration|Expression
*/
public function getDeclaration()
{
return $this->declaration;
}
/**
* Sets the exported declaration
*
* @param Declaration|Expression $declaration The exported declaration
*
* @return $this
*/
public function setDeclaration($declaration)
{
$this->assertType($declaration, array("Declaration", "Expression"));
$this->declaration = $declaration;
return $this;
}
}

View File

@@ -0,0 +1,123 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents an export named declaration.
* For example: export {foo} from "bar"
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ExportNamedDeclaration extends Node implements ModuleDeclaration
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"declaration" => true,
"specifiers" => true,
"source" => true
);
/**
* Exported declaration
*
* @var Declaration
*/
protected $declaration;
/**
* Exported specifiers
*
* @var ExportSpecifier[]
*/
protected $specifiers = array();
/**
* The export source
*
* @var Literal
*/
protected $source;
/**
* Returns the exported declaration
*
* @return Declaration
*/
public function getDeclaration()
{
return $this->declaration;
}
/**
* Sets the exported declaration
*
* @param Declaration $declaration Exported declaration
*
* @return $this
*/
public function setDeclaration($declaration)
{
$this->assertType($declaration, "Declaration", true);
$this->declaration = $declaration;
return $this;
}
/**
* Return the exported specifiers
*
* @return ExportSpecifier[]
*/
public function getSpecifiers()
{
return $this->specifiers;
}
/**
* Sets the exported specifiers
*
* @param ExportSpecifier[] $specifiers Exported specifiers
*
* @return $this
*/
public function setSpecifiers($specifiers)
{
$this->assertArrayOf($specifiers, "ExportSpecifier");
$this->specifiers = $specifiers;
return $this;
}
/**
* Returns the export source
*
* @return Literal
*/
public function getSource()
{
return $this->source;
}
/**
* Sets the export source
*
* @param Literal $source Export source
*
* @return $this
*/
public function setSource($source)
{
$this->assertType($source, "Literal", true);
$this->source = $source;
return $this;
}
}

View File

@@ -0,0 +1,59 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a specifier in an export declaration.
* For example "{a}" in: export {a}
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ExportSpecifier extends ModuleSpecifier
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"exported" => true
);
/**
* Exported identifier
*
* @var Identifier|StringLiteral
*/
protected $exported;
/**
* Returns the exported identifier
*
* @return Identifier|StringLiteral
*/
public function getExported()
{
return $this->exported;
}
/**
* Sets the exported identifier
*
* @param Identifier|StringLiteral $exported Exported identifier
*
* @return $this
*/
public function setExported($exported)
{
$this->assertType($exported, array("Identifier", "StringLiteral"));
$this->exported = $exported;
return $this;
}
}

View File

@@ -0,0 +1,19 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* Interface that every expression node must implement.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
interface Expression
{
}

View File

@@ -0,0 +1,57 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents an expression statement and wraps another expression.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ExpressionStatement extends Node implements Statement
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"expression" => true
);
/**
* Wrapped expression
*
* @var Expression
*/
protected $expression;
/**
* Returns the wrapped expression
*
* @return Expression
*/
public function getExpression()
{
return $this->expression;
}
/**
* Sets the wrapped expression
*
* @param Expression $expression Wrapped expression
*
* @return $this
*/
public function setExpression(Expression $expression)
{
$this->expression = $expression;
return $this;
}
}

View File

@@ -0,0 +1,123 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a for-in statement.
* For example: for (var a in b) {}
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ForInStatement extends Node implements Statement
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"left" => true,
"right" => true,
"body" => true
);
/**
* Iteration variable
*
* @var VariableDeclaration|Expression|Pattern
*/
protected $left;
/**
* Iterated object
*
* @var Expression
*/
protected $right;
/**
* Loop body
*
* @var Statement
*/
protected $body;
/**
* Returns the iteration variable
*
* @return VariableDeclaration|Expression|Pattern
*/
public function getLeft()
{
return $this->left;
}
/**
* Sets the iteration variable
*
* @param VariableDeclaration|Expression|Pattern $left Iteration variable
*
* @return $this
*/
public function setLeft($left)
{
$this->assertType(
$left, array("VariableDeclaration", "Expression", "Pattern")
);
$this->left = $left;
return $this;
}
/**
* Returns the iterated object
*
* @return Expression
*/
public function getRight()
{
return $this->right;
}
/**
* Sets the iterated object
*
* @param Expression $right Iterated object
*
* @return $this
*/
public function setRight(Expression $right)
{
$this->right = $right;
return $this;
}
/**
* Returns the loop body
*
* @return Statement
*/
public function getBody()
{
return $this->body;
}
/**
* Sets the loop body
*
* @param Statement $body Loop body
*
* @return $this
*/
public function setBody(Statement $body)
{
$this->body = $body;
return $this;
}
}

View File

@@ -0,0 +1,61 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents the "for...of" statement.
* For example: for (var a of b) {}
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ForOfStatement extends ForInStatement
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"left" => true,
"right" => true,
"body" => true,
"await" => false
);
/**
* Async iteration flag
*
* @var bool
*/
protected $await = false;
/**
* Returns the async iteration flag
*
* @return bool
*/
public function getAwait()
{
return $this->await;
}
/**
* Sets the async iteration flag
*
* @param bool $await Async iteration flag
*
* @return $this
*/
public function setAwait($await)
{
$this->await = (bool) $await;
return $this;
}
}

View File

@@ -0,0 +1,157 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a for statement.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ForStatement extends Node implements Statement
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"init" => true,
"test" => true,
"update" => true,
"body" => true
);
/**
* Initializer
*
* @var VariableDeclaration|Expression
*/
protected $init;
/**
* Test expression
*
* @var Expression
*/
protected $test;
/**
* Update expression
*
* @var Expression
*/
protected $update;
/**
* Loop body
*
* @var Statement
*/
protected $body;
/**
* Returns the initializer
*
* @return VariableDeclaration|Expression
*/
public function getInit()
{
return $this->init;
}
/**
* Sets the initializer
*
* @param VariableDeclaration|Expression $init Initializer
*
* @return $this
*/
public function setInit($init)
{
$this->assertType(
$init,
array("VariableDeclaration", "Expression"),
true
);
$this->init = $init;
return $this;
}
/**
* Returns the test expression
*
* @return Expression
*/
public function getTest()
{
return $this->test;
}
/**
* Sets the test expression
*
* @param Expression $test Test expression
*
* @return $this
*/
public function setTest($test)
{
$this->assertType($test, "Expression", true);
$this->test = $test;
return $this;
}
/**
* Returns the update expression
*
* @return Expression
*/
public function getUpdate()
{
return $this->update;
}
/**
* Sets the update expression
*
* @param Expression $update Update expression
*
* @return $this
*/
public function setUpdate($update)
{
$this->assertType($update, "Expression", true);
$this->update = $update;
return $this;
}
/**
* Returns the loop body
*
* @return Statement
*/
public function getBody()
{
return $this->body;
}
/**
* Sets the loop body
*
* @param Statement $body Loop body
*
* @return $this
*/
public function setBody(Statement $body)
{
$this->body = $body;
return $this;
}
}

View File

@@ -0,0 +1,33 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a function declaration
* For example: function test () {}
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class FunctionDeclaration extends Function_ implements Declaration
{
/**
* Sets the function identifier
*
* @param Identifier $id Function identifier
*
* @return $this
*/
public function setId($id)
{
$this->assertType($id, "Identifier");
$this->id = $id;
return $this;
}
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a function expression
* For example: var test = function () {}
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class FunctionExpression extends Function_ implements Expression
{
}

View File

@@ -0,0 +1,184 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* Abstract class for functions.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
abstract class Function_ extends Node
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"id" => true,
"params" => true,
"body" => true,
"generator" => false,
"async" => false
);
/**
* Function name
*
* @var Identifier
*/
protected $id;
/**
* Function parameters array
*
* @var Pattern[]
*/
protected $params = array();
/**
* Function body
*
* @var BlockStatement
*/
protected $body;
/**
* Generator flag that is true when the function is a generator
*
* @var bool
*/
protected $generator = false;
/**
* Async flag that is true when it is an async function
*
* @var bool
*/
protected $async = false;
/**
* Returns function name
*
* @return Identifier
*/
public function getId()
{
return $this->id;
}
/**
* Sets function name
*
* @param Identifier $id Function name
*
* @return $this
*/
public function setId($id)
{
$this->assertType($id, "Identifier", true);
$this->id = $id;
return $this;
}
/**
* Returns function parameters array
*
* @return Pattern[]
*/
public function getParams()
{
return $this->params;
}
/**
* Sets function parameters array
*
* @param Pattern[] $params Function parameters array
*
* @return $this
*/
public function setParams($params)
{
$this->assertArrayOf($params, "Pattern");
$this->params = $params;
return $this;
}
/**
* Returns function body
*
* @return BlockStatement
*/
public function getBody()
{
return $this->body;
}
/**
* Sets function body
*
* @param BlockStatement $body Function body
*
* @return $this
*/
public function setBody($body)
{
$this->assertType($body, "BlockStatement");
$this->body = $body;
return $this;
}
/**
* Returns the generator flag that is true when the function is a generator
*
* @return bool
*/
public function getGenerator()
{
return $this->generator;
}
/**
* Sets the generator flag that is true when the function is a generator
*
* @param bool $generator Generator flag
*
* @return $this
*/
public function setGenerator($generator)
{
$this->generator = (bool) $generator;
return $this;
}
/**
* Returns the async flag that is true when it is an async function
*
* @return bool
*/
public function getAsync()
{
return $this->async;
}
/**
* Sets the async flag that is true when it is an async function
*
* @param bool $async Async flag
*
* @return $this
*/
public function setAsync($async)
{
$this->async = (bool) $async;
return $this;
}
}

View File

@@ -0,0 +1,101 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
use Peast\Syntax\Utils;
/**
* A node that represents an identifier.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class Identifier extends Node implements Expression, Pattern
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"name" => false,
"rawName" => false,
);
/**
* The identifier's name
*
* @var string
*/
protected $name;
/**
* The identifier's raw name
*
* @var string
*/
protected $rawName;
/**
* Returns the identifier's name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Sets the identifier's name
*
* @param string $name The name to set
*
* @return $this
*/
public function setName($name)
{
$this->name = $this->rawName = $name;
return $this;
}
/**
* Returns the identifier's raw name
*
* @return string
*/
public function getRawName()
{
return $this->rawName;
}
/**
* Sets the identifier's raw name
*
* @param string $name The raw name to set
*
* @return $this
*/
public function setRawName($name)
{
$this->rawName = $name;
if (strpos($name, "\\") !== false) {
$this->name = preg_replace_callback(
"#\\\\u(?:\{([a-fA-F0-9]+)\}|([a-fA-F0-9]{4}))#",
function ($match) {
return Utils::unicodeToUtf8(hexdec($match[1] ? : $match[2]));
},
$name
);
} else {
$this->name = $name;
}
return $this;
}
}

View File

@@ -0,0 +1,130 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents an if statement.
* For example: if (test) {} else {}
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class IfStatement extends Node implements Statement
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"test" => true,
"consequent" => true,
"alternate" => true
);
/**
* The test expression
*
* @var Expression
*/
protected $test;
/**
* The statement that is activated if the test expression is true
*
* @var Statement|FunctionDeclaration
*/
protected $consequent;
/**
* The "else" statement
*
* @var Statement
*/
protected $alternate;
/**
* Returns the test expression
*
* @return Expression
*/
public function getTest()
{
return $this->test;
}
/**
* Sets the test expression
*
* @param Expression $test Test expression
*
* @return $this
*/
public function setTest(Expression $test)
{
$this->test = $test;
return $this;
}
/**
* Returns the statement that is activated if the test expression is true
*
* @return Statement|FunctionDeclaration
*/
public function getConsequent()
{
return $this->consequent;
}
/**
* Sets the statement that is activated if the test expression is true
*
* @param Statement|FunctionDeclaration $consequent The consequent expression
*
* @return $this
*/
public function setConsequent($consequent)
{
$this->assertType(
$consequent,
array("Statement", "FunctionDeclaration"),
true
);
$this->consequent = $consequent;
return $this;
}
/**
* Returns the "else" statement
*
* @return Statement
*/
public function getAlternate()
{
return $this->alternate;
}
/**
* Sets the "else" statement
*
* @param Statement|FunctionDeclaration $alternate The "else" statement
*
* @return $this
*/
public function setAlternate($alternate)
{
$this->assertType(
$alternate,
array("Statement", "FunctionDeclaration"),
true
);
$this->alternate = $alternate;
return $this;
}
}

View File

@@ -0,0 +1,97 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents in import declaration.
* For example: import a from "mod"
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ImportDeclaration extends Node implements ModuleDeclaration
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"specifiers" => true,
"source" => true
);
/**
* Import specifiers array
*
* @var array
*/
protected $specifiers = array();
/**
* Import source
*
* @var Literal
*/
protected $source;
/**
* Returns the import specifiers array
*
* @return array
*/
public function getSpecifiers()
{
return $this->specifiers;
}
/**
* Sets the import specifiers array
*
* @param array $specifiers Import specifiers array
*
* @return $this
*/
public function setSpecifiers($specifiers)
{
$this->assertArrayOf(
$specifiers,
array(
"ImportSpecifier",
"ImportDefaultSpecifier",
"ImportNamespaceSpecifier"
)
);
$this->specifiers = $specifiers;
return $this;
}
/**
* Returns the import source
*
* @return Literal
*/
public function getSource()
{
return $this->source;
}
/**
* Sets the import source
*
* @param Literal $source Import source
*
* @return $this
*/
public function setSource(Literal $source)
{
$this->source = $source;
return $this;
}
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a namespace import specifier.
* For example "* as test" in: import * as test from "test.js".
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ImportDefaultSpecifier extends ModuleSpecifier
{
}

View File

@@ -0,0 +1,57 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents an import expression (dynamic import).
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ImportExpression extends Node implements Expression
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"source" => true
);
/**
* The catch clause parameter
*
* @var Expression
*/
protected $source;
/**
* Returns the import source
*
* @return Expression
*/
public function getSource()
{
return $this->source;
}
/**
* Sets the import source
*
* @param Expression $source Import source
*
* @return $this
*/
public function setSource(Expression $source)
{
$this->source = $source;
return $this;
}
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a default import specifier.
* For example "test" in: import test from "test.js".
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ImportNamespaceSpecifier extends ModuleSpecifier
{
}

View File

@@ -0,0 +1,59 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a specifier in an import declaration.
* For example "{a}" in: import {a} from "test"
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ImportSpecifier extends ModuleSpecifier
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"imported" => true
);
/**
* Imported identifier
*
* @var Identifier|StringLiteral
*/
protected $imported;
/**
* Returns the imported identifier
*
* @return Identifier|StringLiteral
*/
public function getImported()
{
return $this->imported;
}
/**
* Sets the imported identifier
*
* @param Identifier|StringLiteral $imported Imported identifier
*
* @return $this
*/
public function setImported($imported)
{
$this->assertType($imported, array("Identifier", "StringLiteral"));
$this->imported = $imported;
return $this;
}
}

View File

@@ -0,0 +1,99 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node\JSX;
use Peast\Syntax\Node\Node;
/**
* A node that represents a JSX attribute.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class JSXAttribute extends Node
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"name" => true,
"value" => true
);
/**
* Attribute name
*
* @var JSXIdentifier|JSXNamespacedName
*/
protected $name;
/**
* Attribute value
*
* @var Node|null
*/
protected $value;
/**
* Returns the attribute name
*
* @return Node
*/
public function getName()
{
return $this->name;
}
/**
* Sets the attribute name
*
* @param JSXIdentifier|JSXNamespacedName $name Attribute name
*
* @return $this
*/
public function setName($name)
{
$this->assertType($name, array("JSX\\JSXIdentifier", "JSX\\JSXNamespacedName"));
$this->name = $name;
return $this;
}
/**
* Returns the attribute value
*
* @return Node|null
*/
public function getValue()
{
return $this->value;
}
/**
* Sets the attribute value
*
* @param Node|null $value Attribute value
*
* @return $this
*/
public function setValue($value)
{
$this->assertType(
$value,
array(
"Literal", "JSX\\JSXExpressionContainer",
"JSX\\JSXElement", "JSX\\JSXFragment"
),
true
);
$this->value = $value;
return $this;
}
}

View File

@@ -0,0 +1,66 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node\JSX;
use Peast\Syntax\Node\Node;
/**
* A base class for boundary elements.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*
* @abstract
*/
abstract class JSXBoundaryElement extends Node
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"name" => true
);
/**
* Element name
*
* @var JSXIdentifier|JSXMemberExpression|JSXNamespacedName
*/
protected $name;
/**
* Returns the element name
*
* @return JSXIdentifier|JSXMemberExpression|JSXNamespacedName
*/
public function getName()
{
return $this->name;
}
/**
* Sets the element name
*
* @param JSXIdentifier|JSXMemberExpression|JSXNamespacedName $name Element
* name
*
* @return $this
*/
public function setName($name)
{
$this->assertType(
$name,
array("JSX\\JSXIdentifier", "JSX\\JSXMemberExpression", "JSX\\JSXNamespacedName")
);
$this->name = $name;
return $this;
}
}

View File

@@ -0,0 +1,19 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node\JSX;
/**
* A node that represents a JSX closing element tag.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class JSXClosingElement extends JSXBoundaryElement
{
}

View File

@@ -0,0 +1,21 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node\JSX;
use Peast\Syntax\Node\Node;
/**
* A node that represents a JSX closing fragment tag.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class JSXClosingFragment extends Node
{
}

View File

@@ -0,0 +1,127 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node\JSX;
use Peast\Syntax\Node\Node;
use Peast\Syntax\Node\Expression;
/**
* A node that represents a JSX element.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class JSXElement extends Node implements Expression
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"openingElement" => true,
"children" => true,
"closingElement" => true
);
/**
* Opening element node
*
* @var JSXOpeningElement
*/
protected $openingElement;
/**
* Children nodes array
*
* @var Node[]
*/
protected $children = array();
/**
* Closing element node
*
* @var JSXClosingElement|null
*/
protected $closingElement;
/**
* Returns the opening element node
*
* @return JSXOpeningElement
*/
public function getOpeningElement()
{
return $this->openingElement;
}
/**
* Sets the opening element node
*
* @param JSXOpeningElement $openingElement Opening element node
*
* @return $this
*/
public function setOpeningElement(JSXOpeningElement $openingElement)
{
$this->openingElement = $openingElement;
return $this;
}
/**
* Returns the children nodes array
*
* @return Node[]
*/
public function getChildren()
{
return $this->children;
}
/**
* Sets the children nodes array
*
* @param Node[] $children Children nodes array
*
* @return $this
*/
public function setChildren($children)
{
$this->assertArrayOf($children, array(
"JSX\\JSXText", "JSX\\JSXExpressionContainer", "JSX\\JSXSpreadChild",
"JSX\\JSXElement", "JSX\\JSXFragment"
));
$this->children = $children;
return $this;
}
/**
* Returns the closing element node
*
* @return JSXClosingElement|null
*/
public function getClosingElement()
{
return $this->closingElement;
}
/**
* Sets the closing element node
*
* @param JSXClosingElement|null $closingElement Closing element node
*
* @return $this
*/
public function setClosingElement($closingElement)
{
$this->assertType($closingElement, "JSX\\JSXClosingElement", true);
$this->closingElement = $closingElement;
return $this;
}
}

View File

@@ -0,0 +1,21 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node\JSX;
use Peast\Syntax\Node\Node;
/**
* A node that represents a JSX empty expression.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class JSXEmptyExpression extends Node
{
}

View File

@@ -0,0 +1,64 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node\JSX;
use Peast\Syntax\Node\Node;
/**
* A node that represents an expression container in JSX.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class JSXExpressionContainer extends Node
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"expression" => true
);
/**
* The wrapped expression
*
* @var \Peast\Syntax\Node\Expression|JSXEmptyExpression
*/
protected $expression;
/**
* Returns the wrapped expression
*
* @return \Peast\Syntax\Node\Expression|JSXEmptyExpression
*/
public function getExpression()
{
return $this->expression;
}
/**
* Sets the wrapped expression
*
* @param \Peast\Syntax\Node\Expression|JSXEmptyExpression $expression Wrapped
* expression
*
* @return $this
*/
public function setExpression($expression)
{
$this->assertType(
$expression,
array("Expression", "JSX\\JSXEmptyExpression")
);
$this->expression = $expression;
return $this;
}
}

View File

@@ -0,0 +1,126 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node\JSX;
use Peast\Syntax\Node\Node;
use Peast\Syntax\Node\Expression;
/**
* A node that represents a JSX fragment.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class JSXFragment extends Node implements Expression
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"openingFragment" => true,
"children" => true,
"closingFragment" => true
);
/**
* Opening fragment node
*
* @var JSXOpeningFragment
*/
protected $openingFragment;
/**
* Children nodes array
*
* @var Node[]
*/
protected $children = array();
/**
* Closing fragment node
*
* @var JSXClosingFragment
*/
protected $closingFragment;
/**
* Returns the opening fragment node
*
* @return JSXOpeningFragment
*/
public function getOpeningFragment()
{
return $this->openingFragment;
}
/**
* Sets the opening fragment node
*
* @param JSXOpeningFragment $openingFragment Opening fragment node
*
* @return $this
*/
public function setOpeningFragment(JSXOpeningFragment $openingFragment)
{
$this->openingFragment = $openingFragment;
return $this;
}
/**
* Returns the children nodes array
*
* @return Node[]
*/
public function getChildren()
{
return $this->children;
}
/**
* Sets the children nodes array
*
* @param Node[] $children Children nodes array
*
* @return $this
*/
public function setChildren($children)
{
$this->assertArrayOf($children, array(
"JSX\\JSXText", "JSX\\JSXExpressionContainer", "JSX\\JSXSpreadChild",
"JSX\\JSXElement", "JSX\\JSXFragment"
));
$this->children = $children;
return $this;
}
/**
* Returns the closing fragment node
*
* @return JSXClosingFragment
*/
public function getClosingFragment()
{
return $this->closingFragment;
}
/**
* Sets the closing fragment node
*
* @param JSXClosingFragment $closingFragment Closing fragment node
*
* @return $this
*/
public function setClosingFragment(JSXClosingFragment $closingFragment)
{
$this->closingFragment = $closingFragment;
return $this;
}
}

View File

@@ -0,0 +1,21 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node\JSX;
use Peast\Syntax\Node\Identifier;
/**
* A node that represents a JSX identifier.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class JSXIdentifier extends Identifier
{
}

View File

@@ -0,0 +1,92 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node\JSX;
use Peast\Syntax\Node\Node;
use Peast\Syntax\Node\Expression;
/**
* A node that represents a JSX member expression.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class JSXMemberExpression extends Node implements Expression
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"object" => true,
"property" => true
);
/**
* Expression's object
*
* @var JSXMemberExpression|JSXIdentifier
*/
protected $object;
/**
* Expression's property
*
* @var JSXIdentifier
*/
protected $property;
/**
* Returns the expression's object
*
* @return JSXMemberExpression|JSXIdentifier
*/
public function getObject()
{
return $this->object;
}
/**
* Sets the expression's object
*
* @param JSXMemberExpression|JSXIdentifier $object Object
*
* @return $this
*/
public function setObject($object)
{
$this->assertType($object, array("JSX\\JSXMemberExpression", "JSX\\JSXIdentifier"));
$this->object = $object;
return $this;
}
/**
* Returns the expression's property
*
* @return JSXIdentifier
*/
public function getProperty()
{
return $this->property;
}
/**
* Sets the expression's property
*
* @param JSXIdentifier $property Property
*
* @return $this
*/
public function setProperty(JSXIdentifier $property)
{
$this->property = $property;
return $this;
}
}

View File

@@ -0,0 +1,91 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node\JSX;
use Peast\Syntax\Node\Node;
use Peast\Syntax\Node\Expression;
/**
* A node that represents a JSX namespaced name.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class JSXNamespacedName extends Node implements Expression
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"namespace" => false,
"name" => false
);
/**
* Node's namespace
*
* @var JSXIdentifier
*/
protected $namespace;
/**
* Node's name
*
* @var JSXIdentifier
*/
protected $name;
/**
* Returns node's namespace
*
* @return JSXIdentifier
*/
public function getNamespace()
{
return $this->namespace;
}
/**
* Sets node's namespace
*
* @param JSXIdentifier $namespace Namespace
*
* @return $this
*/
public function setNamespace($namespace)
{
$this->namespace = $namespace;
return $this;
}
/**
* Return node's name
*
* @return JSXIdentifier
*/
public function getName()
{
return $this->name;
}
/**
* Sets node's name
*
* @param JSXIdentifier $name Name
*
* @return $this
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
}

View File

@@ -0,0 +1,92 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node\JSX;
/**
* A node that represents a JSX opening element tag.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class JSXOpeningElement extends JSXBoundaryElement
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"attributes" => true,
"selfClosing" => false
);
/**
* Children nodes array
*
* @var JSXAttribute[]|JSXSpreadAttribute[]
*/
protected $attributes = array();
/**
* Self closing tag mode
*
* @var bool
*/
protected $selfClosing = false;
/**
* Returns the children attributes array
*
* @return JSXAttribute[]|JSXSpreadAttribute[]
*/
public function getAttributes()
{
return $this->attributes;
}
/**
* Sets the attributes nodes array
*
* @param JSXAttribute[]|JSXSpreadAttribute[] $attributes Attributes nodes
* array
*
* @return $this
*/
public function setAttributes($attributes)
{
$this->assertArrayOf($attributes, array(
"JSX\\JSXAttribute", "JSX\\JSXSpreadAttribute"
));
$this->attributes = $attributes;
return $this;
}
/**
* Returns the self closing tag mode
*
* @return bool
*/
public function getSelfClosing()
{
return $this->selfClosing;
}
/**
* Sets the self closing tag mode
*
* @param bool $selfClosing Self closing tag mode
*
* @return $this
*/
public function setSelfClosing($selfClosing)
{
$this->selfClosing = (bool) $selfClosing;
return $this;
}
}

View File

@@ -0,0 +1,21 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node\JSX;
use Peast\Syntax\Node\Node;
/**
* A node that represents a JSX opening fragment tag.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class JSXOpeningFragment extends Node
{
}

View File

@@ -0,0 +1,21 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node\JSX;
use Peast\Syntax\Node\SpreadElement;
/**
* A node that represents a JSX spread attribute.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class JSXSpreadAttribute extends SpreadElement
{
}

View File

@@ -0,0 +1,60 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node\JSX;
use Peast\Syntax\Node\Node;
use Peast\Syntax\Node\Expression;
/**
* A node that represents a spread child expression in JSX.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class JSXSpreadChild extends Node
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"expression" => true
);
/**
* The wrapped expression
*
* @var Expression
*/
protected $expression;
/**
* Returns the wrapped expression
*
* @return Expression
*/
public function getExpression()
{
return $this->expression;
}
/**
* Sets the wrapped expression
*
* @param Expression $expression Wrapped expression
*
* @return $this
*/
public function setExpression(Expression $expression)
{
$this->expression = $expression;
return $this;
}
}

View File

@@ -0,0 +1,90 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node\JSX;
use Peast\Syntax\Node\Node;
/**
* A node that represents a JSX closing fragment tag.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class JSXText extends Node
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"value" => false,
"raw" => false
);
/**
* Node's value
*
* @var mixed
*/
protected $value;
/**
* Node's raw value
*
* @var string
*/
protected $raw;
/**
* Returns node's value
*
* @return mixed
*/
public function getValue()
{
return $this->value;
}
/**
* Sets node's value
*
* @param mixed $value Value
*
* @return $this
*/
public function setValue($value)
{
$this->value = $value;
$this->raw = $value;
return $this;
}
/**
* Return node's raw value
*
* @return string
*/
public function getRaw()
{
return $this->raw;
}
/**
* Sets node's raw value
*
* @param mixed $raw Raw value
*
* @return $this
*/
public function setRaw($raw)
{
return $this->setValue($raw);
}
}

View File

@@ -0,0 +1,88 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a labeled statement.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class LabeledStatement extends Node implements Statement
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"label" => true,
"body" => true
);
/**
* Label
*
* @var Identifier
*/
protected $label;
/**
* Body
*
* @var Statement
*/
protected $body;
/**
* Returns the label
*
* @return Identifier
*/
public function getLabel()
{
return $this->label;
}
/**
* Sets the label
*
* @param Identifier $label Label
*
* @return $this
*/
public function setLabel(Identifier $label)
{
$this->label = $label;
return $this;
}
/**
* Returns the body
*
* @return Statement
*/
public function getBody()
{
return $this->body;
}
/**
* Sets the body
*
* @param Statement $body Body
*
* @return $this
*/
public function setBody(Statement $body)
{
$this->body = $body;
return $this;
}
}

View File

@@ -0,0 +1,93 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* Abstract class for literals.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
abstract class Literal extends Node implements Expression
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"value" => false,
"raw" => false
);
/**
* Node's value
*
* @var mixed
*/
protected $value;
/**
* Node's raw value
*
* @var string
*/
protected $raw;
/**
* Returns node's type
*
* @return string
*/
public function getType()
{
return "Literal";
}
/**
* Returns node's value
*
* @return mixed
*/
public function getValue()
{
return $this->value;
}
/**
* Sets node's value
*
* @param mixed $value Value
*
* @return $this
*/
abstract public function setValue($value);
/**
* Return node's raw value
*
* @return string
*/
public function getRaw()
{
return $this->raw;
}
/**
* Sets node's raw value
*
* @param mixed $raw Raw value
*
* @return $this
*/
public function setRaw($raw)
{
return $this->setValue($raw);
}
}

View File

@@ -0,0 +1,120 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a logical expression.
* For example: a && b
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class LogicalExpression extends Node implements Expression
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"left" => true,
"operator" => false,
"right" => true
);
/**
* Operator
*
* @var string
*/
protected $operator;
/**
* Left expression
*
* @var Expression
*/
protected $left;
/**
* Right expression
*
* @var Expression
*/
protected $right;
/**
* Returns the operator
*
* @return string
*/
public function getOperator()
{
return $this->operator;
}
/**
* Sets the operator
*
* @param string $operator Operator
*
* @return $this
*/
public function setOperator($operator)
{
$this->operator = $operator;
return $this;
}
/**
* Returns the left expression
*
* @return Expression
*/
public function getLeft()
{
return $this->left;
}
/**
* Sets the left expression
*
* @param Expression $left Left expression
*
* @return $this
*/
public function setLeft(Expression $left)
{
$this->left = $left;
return $this;
}
/**
* Returns the right expression
*
* @return Expression
*/
public function getRight()
{
return $this->right;
}
/**
* Sets the right expression
*
* @param Expression $right Right expression
*
* @return $this
*/
public function setRight(Expression $right)
{
$this->right = $right;
return $this;
}
}

View File

@@ -0,0 +1,125 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a member expression.
* For example: foo.bar
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class MemberExpression extends ChainElement implements Pattern
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"object" => true,
"property" => true,
"computed" => false
);
/**
* Expression's object
*
* @var Expression|Super
*/
protected $object;
/**
* Expression's property
*
* @var Expression|PrivateIdentifier
*/
protected $property;
/**
* Computed flag that is true if the property is declared using square
* brackets syntax
*
* @var bool
*/
protected $computed = false;
/**
* Returns the expression's object
*
* @return Expression|Super
*/
public function getObject()
{
return $this->object;
}
/**
* Sets the expression's object
*
* @param Expression|Super $object Object
*
* @return $this
*/
public function setObject($object)
{
$this->assertType($object, array("Expression", "Super"));
$this->object = $object;
return $this;
}
/**
* Returns the expression's property
*
* @return Expression|PrivateIdentifier
*/
public function getProperty()
{
return $this->property;
}
/**
* Sets the expression's property
*
* @param Expression|PrivateIdentifier $property Property
*
* @return $this
*/
public function setProperty($property)
{
$this->assertType($property, array("Expression", "PrivateIdentifier"));
$this->property = $property;
return $this;
}
/**
* Returns the computed flag that is true if the property is declared
* using square brackets syntax
*
* @return bool
*/
public function getComputed()
{
return $this->computed;
}
/**
* Sets the computed flag that is true if the property is declared
* using square brackets syntax
*
* @param bool $computed Computed flag
*
* @return $this
*/
public function setComputed($computed)
{
$this->computed = (bool) $computed;
return $this;
}
}

View File

@@ -0,0 +1,89 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a meta property.
* For example: new.target
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class MetaProperty extends Node implements Expression
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"meta" => false,
"property" => false
);
/**
* Subject
*
* @var string
*/
protected $meta;
/**
* Property
*
* @var string
*/
protected $property;
/**
* Returns the subject
*
* @return string
*/
public function getMeta()
{
return $this->meta;
}
/**
* Sets the subject
*
* @param string $meta Subject
*
* @return $this
*/
public function setMeta($meta)
{
$this->meta = $meta;
return $this;
}
/**
* Returns the property
*
* @return string
*/
public function getProperty()
{
return $this->property;
}
/**
* Sets the property
*
* @param string $property Property
*
* @return $this
*/
public function setProperty($property)
{
$this->property = $property;
return $this;
}
}

View File

@@ -0,0 +1,206 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a method declaration in classes and object literals.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class MethodDefinition extends Node
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"key" => true,
"value" => true,
"kind" => false,
"computed" => false,
"static" => false
);
//Kind constants
/**
* Constructor method
*/
const KIND_CONSTRUCTOR = "constructor";
/**
* Standard method
*/
const KIND_METHOD = "method";
/**
* Getter method
*/
const KIND_GET = "get";
/**
* Setter method
*/
const KIND_SET = "set";
/**
* Method's key
*
* @var Expression|PrivateIdentifier
*/
protected $key;
/**
* Method's value
*
* @var FunctionExpression
*/
protected $value;
/**
* Method's kind that is one of the kind constants
*
* @var string
*/
protected $kind = self::KIND_METHOD;
/**
* Computed flag that is true if method's key is declared using square
* brackets syntax
*
* @var bool
*/
protected $computed = false;
/**
* Static flag that is true if the method is static
*
* @var bool
*/
protected $static = false;
/**
* Returns the method's key
*
* @return Expression|PrivateIdentifier
*/
public function getKey()
{
return $this->key;
}
/**
* Sets the method's key
*
* @param Expression|PrivateIdentifier $key Method's key
*
* @return $this
*/
public function setKey($key)
{
$this->assertType($key, array("Expression", "PrivateIdentifier"));
$this->key = $key;
return $this;
}
/**
* Returns the method's value
*
* @return FunctionExpression
*/
public function getValue()
{
return $this->value;
}
/**
* Sets the method's value
*
* @param FunctionExpression $value Method's value
*
* @return $this
*/
public function setValue(FunctionExpression $value)
{
$this->value = $value;
return $this;
}
/**
* Returns the method's kind that is one of the kind constants
*
* @return string
*/
public function getKind()
{
return $this->kind;
}
/**
* Sets the method's kind that is one of the kind constants
*
* @param string $kind Method's kind
*
* @return $this
*/
public function setKind($kind)
{
$this->kind = $kind;
return $this;
}
/**
* Returns the computed flag that is true if method's key is declared using
* square brackets syntax
*
* @return bool
*/
public function getComputed()
{
return $this->computed;
}
/**
* Sets the computed flag that is true if method's key is declared using
* square brackets syntax
*
* @param bool $computed Computed flag
*
* @return $this
*/
public function setComputed($computed)
{
$this->computed = (bool) $computed;
return $this;
}
/**
* Returns the static flag that is true if the method is static
*
* @return bool
*/
public function getStatic()
{
return $this->{"static"};
}
/**
* Sets the static flag that is true if the method is static
*
* @param bool $static Static flag
*
* @return $this
*/
public function setStatic($static)
{
$this->{"static"} = (bool) $static;
return $this;
}
}

View File

@@ -0,0 +1,19 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* Common interface for function import and export nodes.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
interface ModuleDeclaration
{
}

View File

@@ -0,0 +1,60 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* Abstract class that export and import specifiers nodes must extend.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*
* @abstract
*/
abstract class ModuleSpecifier extends Node
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"local" => true
);
/**
* Local identifier
*
* @var Identifier|StringLiteral
*/
protected $local;
/**
* Returns the local identifier
*
* @return Identifier|StringLiteral
*/
public function getLocal()
{
return $this->local;
}
/**
* Sets the local identifier
*
* @param Identifier|StringLiteral $local Local identifier
*
* @return $this
*/
public function setLocal($local)
{
$this->assertType($local, array("Identifier", "StringLiteral"));
$this->local = $local;
return $this;
}
}

View File

@@ -0,0 +1,20 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a "new" expression.
* For example: new test()
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class NewExpression extends CallExpression
{
}

View File

@@ -0,0 +1,320 @@
<?php /** @noinspection PhpElementIsNotAvailableInCurrentPhpVersionInspection */
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
use Peast\Syntax\SourceLocation;
use Peast\Syntax\Position;
/**
* Base class for all the nodes generated by Peast.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*
* @abstract
*/
abstract class Node implements \JSONSerializable
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"type" => false,
"location" => false,
"leadingComments" => false,
"trailingComments" => false
);
/**
* Node location in the source code
*
* @var SourceLocation
*/
public $location;
/**
* Leading comments array
*
* @var Comment[]
*/
protected $leadingComments = array();
/**
* Trailing comments array
*
* @var Comment[]
*/
protected $trailingComments = array();
/**
* Class constructor
*/
public function __construct()
{
$this->location = new SourceLocation;
}
/**
* Returns node type
*
* @return string
*/
public function getType()
{
$class = explode("\\", get_class($this));
return array_pop($class);
}
/**
* Sets leading comments array
*
* @param Comment[] $comments Comments array
*
* @return $this
*/
public function setLeadingComments($comments)
{
$this->assertArrayOf($comments, "Comment");
$this->leadingComments = $comments;
return $this;
}
/**
* Returns leading comments array
*
* @return Comment[]
*/
public function getLeadingComments()
{
return $this->leadingComments;
}
/**
* Sets trailing comments array
*
* @param Comment[] $comments Comments array
*
* @return $this
*/
public function setTrailingComments($comments)
{
$this->assertArrayOf($comments, "Comment");
$this->trailingComments = $comments;
return $this;
}
/**
* Returns trailing comments array
*
* @return Comment[]
*/
public function getTrailingComments()
{
return $this->trailingComments;
}
/**
* Returns node location in the source code
*
* @return SourceLocation
*/
public function getLocation()
{
return $this->location;
}
/**
* Sets the start position of the node in the source code
*
* @param Position $position Start position
*
* @return $this
*/
public function setStartPosition(Position $position)
{
$this->location->start = $position;
return $this;
}
/**
* Sets the end position of the node in the source code
*
* @param Position $position Start position
*
* @return $this
*/
public function setEndPosition(Position $position)
{
$this->location->end = $position;
return $this;
}
/**
* Traverses the current node and all its child nodes using the given
* function
*
* @param callable $fn Function that will be called on each node
* @param array $options Options array. See Traverser class
* documentation for available options
*
* @return $this
*/
public function traverse(callable $fn, $options = array())
{
$traverser = new \Peast\Traverser($options);
$traverser->addFunction($fn)->traverse($this);
return $this;
}
/**
* Returns a serializable version of the node
*
* @return array
*/
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
$ret = array();
$props = \Peast\Syntax\Utils::getNodeProperties($this);
foreach ($props as $prop) {
$ret[$prop["name"]] = $this->{$prop["getter"]}();
}
return $ret;
}
/**
* Renders the current node
*
* @param \Peast\Formatter\Base $formatter Formatter to use for the
* rendering
*
* @return string
*/
public function render(\Peast\Formatter\Base $formatter)
{
$renderer = new \Peast\Renderer();
return $renderer->setFormatter($formatter)->render($this);
}
/**
* Asserts that the given value is an array of defined type
*
* @param mixed $params Value to check
* @param string|array $classes Class or array of classes to check against
* @param bool $allowNull If true, null values are allowed
*
* @return void
*
* @codeCoverageIgnore
*/
protected function assertArrayOf($params, $classes, $allowNull = false)
{
if (!is_array($classes)) {
$classes = array($classes);
}
if (!is_array($params)) {
$this->typeError($params, $classes, $allowNull, true);
} else {
foreach ($params as $param) {
foreach ($classes as $class) {
if ($param === null && $allowNull) {
continue 2;
} else {
$c = "Peast\\Syntax\\Node\\$class";
if ($param instanceof $c) {
continue 2;
}
}
}
$this->typeError($param, $classes, $allowNull, true, true);
}
}
}
/**
* Asserts that the given value respects the defined type
*
* @param mixed $param Value to check
* @param string|array $classes Class or array of classes to check against
* @param bool $allowNull If true, null values are allowed
*
* @return void
*
* @codeCoverageIgnore
*/
protected function assertType($param, $classes, $allowNull = false)
{
if (!is_array($classes)) {
$classes = array($classes);
}
if ($param === null) {
if (!$allowNull) {
$this->typeError($param, $classes, $allowNull);
}
} else {
foreach ($classes as $class) {
$c = "Peast\\Syntax\\Node\\$class";
if ($param instanceof $c) {
return;
}
}
$this->typeError($param, $classes, $allowNull);
}
}
/**
* Throws an error if the defined type is not supported b
*
* @param mixed $param The value to check
* @param mixed $allowedTypes Class or array of classes to check against
* @param bool $allowNull If true, null values are allowed
* @param bool $array If true, the value must be an array
* @param bool $inArray If true, the value is an array but the content
* does not respects the type
*
* @return void
*
* @throws \TypeError
*
* @codeCoverageIgnore
*/
protected function typeError(
$param, $allowedTypes, $allowNull = false, $array = false,
$inArray = false
) {
$backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
$method = $backtrace[2]["class"] . "::" . $backtrace[2]["function"];
$msg = "Argument 0 passed to $method must be ";
if ($array) {
$msg .= "an array of ";
}
$msg .= implode(" or ", $allowedTypes);
if ($allowNull) {
$msg .= " or null";
}
if (is_object($param)) {
$parts = explode("\\", get_class($param));
$type = array_pop($parts);
} else {
$type = gettype($param);
}
if ($inArray) {
$type = "array of $type";
}
$msg .= ", $type given";
if (version_compare(phpversion(), '7', '>=')) {
throw new \TypeError($msg);
} else {
trigger_error($msg, E_USER_ERROR);
}
}
}

View File

@@ -0,0 +1,44 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a null literal.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class NullLiteral extends Literal
{
/**
* Node's value
*
* @var mixed
*/
protected $value = null;
/**
* Node's raw value
*
* @var string
*/
protected $raw = "null";
/**
* Sets node's value
*
* @param mixed $value Value
*
* @return $this
*/
public function setValue($value)
{
return $this;
}
}

View File

@@ -0,0 +1,191 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a numeric literal.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class NumericLiteral extends Literal
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"format" => false
);
//Format constants
/**
* Decimal number format
*/
const DECIMAL = "decimal";
/**
* Hexadecimal number format
*/
const HEXADECIMAL = "hexadecimal";
/**
* Octal number format
*/
const OCTAL = "octal";
/**
* Binary number format
*/
const BINARY = "binary";
/**
* Node's numeric format
*
* @var string
*/
protected $format = self::DECIMAL;
/**
* Numeric forms conversion rules
*
* @var array
*/
protected $forms = array(
"b" => array(
"check" => "/^0b[01]+[01_]*$/i",
"conv" => "bindec",
"format" => self::BINARY
),
"o" => array(
"check" => "/^0o[0-7]+[0-7_]*$/i",
"conv" => "octdec",
"format" => self::OCTAL
),
"x" => array(
"check" => "/^0x[0-9a-f]+[0-9a-f_]*$/i",
"conv" => "hexdec",
"format" => self::HEXADECIMAL
),
);
/**
* Sets node's value
*
* @param float $value Value
*
* @return $this
*/
public function setValue($value)
{
$value = (float) $value;
$intValue = (int) $value;
if ($value == $intValue) {
$value = $intValue;
}
$this->value = $value;
//Force recalculation of the raw value
return $this->setFormat($this->format);
}
/**
* Sets node's raw value
*
* @param mixed $raw Raw value
*
* @return $this
*
* @throws \Exception
*/
public function setRaw($raw)
{
$value = $raw;
$format = self::DECIMAL;
if (is_string($value) && $value !== "") {
//Hexadecimal, binary or octal
$startZero = $value[0] === "0";
$form = $startZero && isset($value[1]) ? strtolower($value[1]) : null;
//Numeric separator cannot appear at the beginning or at the end of the number
if (preg_match("/^_|_$/", $value)) {
throw new \Exception("Invalid numeric value");
} elseif (isset($this->forms[$form])) {
$formDef = $this->forms[$form];
if (!preg_match($formDef["check"], $value)) {
throw new \Exception("Invalid " . $formDef["format"]);
}
$value = str_replace("_", "", $value);
$value = $formDef["conv"]($value);
$format = $formDef["format"];
} elseif ($startZero && preg_match("/^0[0-7_]+$/", $value)) {
//Legacy octal form
$value = str_replace("_", "", $value);
$value = octdec($value);
$format = self::OCTAL;
} elseif (
preg_match("/^([\d_]*\.?[\d_]*)(?:e[+\-]?[\d_]+)?$/i", $value, $match) &&
$match[1] !== "" &&
$match[1] !== "." &&
!preg_match("/_e|e[+-]?_|_$/", $value)
) {
$value = str_replace("_", "", $value);
} else {
throw new \Exception("Invalid numeric value");
}
} elseif (!is_int($value) && !is_float($value)) {
throw new \Exception("Invalid numeric value");
}
$value = (float) $value;
$intValue = (int) $value;
if ($value == $intValue) {
$value = $intValue;
}
$this->format = $format;
$this->value = $value;
$this->raw = $raw;
return $this;
}
/**
* Returns node's numeric format
*
* @return string
*/
public function getFormat()
{
return $this->format;
}
/**
* Sets node's numeric format
*
* @param string $format Format, one of the format constants
*
* @return $this
*/
public function setFormat($format)
{
$this->format = $format;
switch ($format) {
case self::BINARY:
$this->raw = "0b" . decbin($this->value);
break;
case self::OCTAL:
$this->raw = "0o" . decoct($this->value);
break;
case self::HEXADECIMAL:
$this->raw = "0x" . dechex($this->value);
break;
default:
$this->raw = (string) $this->value;
break;
}
return $this;
}
}

View File

@@ -0,0 +1,59 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents an object literal.
* For example: {a: 1, b: 2, c: 3}
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ObjectExpression extends Node implements Expression
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"properties" => true
);
/**
* Object properties
*
* @var Property[]
*/
protected $properties = array();
/**
* Returns object properties
*
* @return Property[]
*/
public function getProperties()
{
return $this->properties;
}
/**
* Sets object properties
*
* @param Property[] $properties Object properties
*
* @return $this
*/
public function setProperties($properties)
{
$this->assertArrayOf($properties, array("Property", "SpreadElement"));
$this->properties = $properties;
return $this;
}
}

View File

@@ -0,0 +1,59 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents an object binding pattern.
* For example: var {a, b, c} = d
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ObjectPattern extends Node implements Pattern
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"properties" => true
);
/**
* Object properties
*
* @var Property[]
*/
protected $properties = array();
/**
* Returns object properties
*
* @return Property[]
*/
public function getProperties()
{
return $this->properties;
}
/**
* Sets object properties
*
* @param Property[] $properties Object properties
*
* @return $this
*/
public function setProperties($properties)
{
$this->assertArrayOf($properties, array("AssignmentProperty", "RestElement"));
$this->properties = $properties;
return $this;
}
}

View File

@@ -0,0 +1,57 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents an expression wrapped in round brackets.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class ParenthesizedExpression extends Node implements Expression
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"expression" => true
);
/**
* The wrapped expression
*
* @var Expression
*/
protected $expression;
/**
* Returns the wrapped expression
*
* @return Expression
*/
public function getExpression()
{
return $this->expression;
}
/**
* Sets the wrapped expression
*
* @param Expression $expression Wrapped expression
*
* @return $this
*/
public function setExpression(Expression $expression)
{
$this->expression = $expression;
return $this;
}
}

View File

@@ -0,0 +1,19 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* Interface that every pattern node must implement.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
interface Pattern
{
}

View File

@@ -0,0 +1,57 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a private identifier.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class PrivateIdentifier extends Node
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"name" => false
);
/**
* The identifier's name
*
* @var string
*/
protected $name;
/**
* Returns the identifier's name
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Sets the identifier's name
*
* @param string $name The name to set
*
* @return $this
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
}

View File

@@ -0,0 +1,111 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
use Peast\Query;
use Peast\Selector;
/**
* Root node for scripts and modules.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class Program extends Node
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"body" => true,
"sourceType" => false
);
/**
* Source type that is one of the source type constants in the Peast class
*
* @var string
*/
protected $sourceType = \Peast\Peast::SOURCE_TYPE_SCRIPT;
/**
* Program's body
*
* @var Statement[]|ModuleDeclaration[]
*/
protected $body = array();
/**
* Returns the source type that is one of the source type constants in the
* Peast class
*
* @return string
*/
public function getSourceType()
{
return $this->sourceType;
}
/**
* Sets the source type that is one of the source type constants in the
* Peast class
*
* @param string $sourceType Source type
*
* @return $this
*/
public function setSourceType($sourceType)
{
$this->sourceType = $sourceType;
return $this;
}
/**
* Returns the program's body
*
* @return Statement[]|ModuleDeclaration[]
*/
public function getBody()
{
return $this->body;
}
/**
* Sets the program's body
*
* @param Statement[]|ModuleDeclaration[] $body Program's body
*
* @return $this
*/
public function setBody($body)
{
$this->assertArrayOf($body, array("Statement", "ModuleDeclaration"));
$this->body = $body;
return $this;
}
/**
* Finds nodes matching the given selector.
*
* @param string $selector Selector
* @param array $options Options array. See Query class
* documentation for available options
*
* @return Query
*
* @throws Selector\Exception
*/
public function query($selector, $options = array())
{
$query = new Query($this, $options);
return $query->find($selector);
}
}

View File

@@ -0,0 +1,237 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a property in an object literal.
* For example "b" in: a = {b: 1}
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class Property extends Node
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"key" => true,
"value" => true,
"kind" => false,
"method" => false,
"shorthand" => false,
"computed" => false
);
//Kind constants
/**
* The default kind for properties
*/
const KIND_INIT = "init";
/**
* Getter property
*/
const KIND_GET = "get";
/**
* Setter property
*/
const KIND_SET = "set";
/**
* Property key
*
* @var Expression
*/
protected $key;
/**
* Property value
*
* @var Expression
*/
protected $value;
/**
* Property kind that is one of the kind constants
*
* @var string
*/
protected $kind = self::KIND_INIT;
/**
* Property method flag that is true when the property is a method
*
* @var bool
*/
protected $method = false;
/**
* Property shorthand flag that is true when the property is declared
* using an identifier and without a value
*
* @var bool
*/
protected $shorthand = false;
/**
* Property computed flag that is true when the property is declared using
* the square brackets syntax
*
* @var bool
*/
protected $computed = false;
/**
* Returns the property key
*
* @return Expression
*/
public function getKey()
{
return $this->key;
}
/**
* Sets the property key
*
* @param Expression $key Property key
*
* @return $this
*/
public function setKey(Expression $key)
{
$this->key = $key;
return $this;
}
/**
* Returns the property value
*
* @return Expression
*/
public function getValue()
{
return $this->value;
}
/**
* Sets the property value
*
* @param Expression $value Property value
*
* @return $this
*/
public function setValue($value)
{
$this->assertType($value, "Expression");
$this->value = $value;
return $this;
}
/**
* Returns the property kind that is one of the kind constants
*
* @return string
*/
public function getKind()
{
return $this->kind;
}
/**
* Sets the property kind that is one of the kind constants
*
* @param string $kind Property kind
*
* @return $this
*/
public function setKind($kind)
{
$this->kind = $kind;
return $this;
}
/**
* Returns the property method flag that is true when the property is a
* method
*
* @return bool
*/
public function getMethod()
{
return $this->method;
}
/**
* Sets the property method flag that is true when the property is a method
*
* @param bool $method Method flag
*
* @return $this
*/
public function setMethod($method)
{
$this->method = (bool) $method;
return $this;
}
/**
* Returns the property shorthand flag that is true when the property
* is declared using an identifier and without a value
*
* @return bool
*/
public function getShorthand()
{
return $this->shorthand;
}
/**
* Sets the property shorthand flag that is true when the property
* is declared using an identifier and without a value
*
* @param bool $shorthand Property shorthand flag
*
* @return $this
*/
public function setShorthand($shorthand)
{
$this->shorthand = (bool) $shorthand;
return $this;
}
/**
* Returns the property computed flag that is true when the property is
* declared using the square brackets syntax
*
* @return bool
*/
public function getComputed()
{
return $this->computed;
}
/**
* Sets the property computed flag that is true when the property is
* declared using the square brackets syntax
*
* @param bool $computed Property computed flag
*
* @return $this
*/
public function setComputed($computed)
{
$this->computed = (bool) $computed;
return $this;
}
}

View File

@@ -0,0 +1,157 @@
<?php
/**
* This file is part of the Peast package
*
* (c) Marco Marchiò <marco.mm89@gmail.com>
*
* For the full copyright and license information refer to the LICENSE file
* distributed with this source code
*/
namespace Peast\Syntax\Node;
/**
* A node that represents a property definition in class body.
*
* @author Marco Marchiò <marco.mm89@gmail.com>
*/
class PropertyDefinition extends Node
{
/**
* Map of node properties
*
* @var array
*/
protected $propertiesMap = array(
"key" => true,
"value" => true,
"computed" => false,
"static" => false
);
/**
* Property key
*
* @var Expression|PrivateIdentifier
*/
protected $key;
/**
* Optional property value
*
* @var Expression|null
*/
protected $value;
/**
* Property computed flag that is true when the property is declared using
* the square brackets syntax
*
* @var bool
*/
protected $computed = false;
/**
* Property static flag that is true when the property is declared static
*
* @var bool
*/
protected $static = false;
/**
* Returns the property key
*
* @return Expression|PrivateIdentifier
*/
public function getKey()
{
return $this->key;
}
/**
* Sets the property key
*
* @param Expression|PrivateIdentifier $key Property key
*
* @return $this
*/
public function setKey($key)
{
$this->assertType($key, array("Expression", "PrivateIdentifier"));
$this->key = $key;
return $this;
}
/**
* Returns the property value
*
* @return Expression|null
*/
public function getValue()
{
return $this->value;
}
/**
* Sets the property value
*
* @param Expression|null $value Property value
*
* @return $this
*/
public function setValue($value)
{
$this->assertType($value, "Expression", true);
$this->value = $value;
return $this;
}
/**
* Returns the property computed flag that is true when the property is
* declared using the square brackets syntax
*
* @return bool
*/
public function getComputed()
{
return $this->computed;
}
/**
* Sets the property computed flag that is true when the property is
* declared using the square brackets syntax
*
* @param bool $computed Property computed flag
*
* @return $this
*/
public function setComputed($computed)
{
$this->computed = (bool) $computed;
return $this;
}
/**
* Returns the property static flag that is true when the property is
* declared static
*
* @return bool
*/
public function getStatic()
{
return $this->static;
}
/**
* Sets the property static flag that is true when the property is
* declared static
*
* @param bool $static Property static flag
*
* @return $this
*/
public function setStatic($static)
{
$this->static = (bool) $static;
return $this;
}
}

Some files were not shown because too many files have changed in this diff Show More