diff options
Diffstat (limited to 'src/Parser/Parser.php')
-rw-r--r-- | src/Parser/Parser.php | 149 |
1 files changed, 130 insertions, 19 deletions
diff --git a/src/Parser/Parser.php b/src/Parser/Parser.php index 05d3726..b0b98f2 100644 --- a/src/Parser/Parser.php +++ b/src/Parser/Parser.php @@ -43,9 +43,17 @@ class Parser $currentStatement = new CommentNode($currentToken); $this->advance(1); } + + else if ($currentToken->type == TokenType::Identifier) { + if ($this->getNextToken()->literal == "=") { + $currentStatement = $this->parseVariableAssignment(); + } + else { + $currentStatement = $this->parseFunctionCall(); + } + } else { - #$currentStatement = $this->parseFunctionCall(); $error = sprintf("Unexpected %s at %d:%d" . PHP_EOL, $currentToken->value, $currentToken->line, $currentToken->column); $this->addError($error); @@ -182,7 +190,7 @@ class Parser // skip const $this->anticipateTokenAndSkip("const"); - $identifier = $this->getCurrentToken(); + $identifier = new IdentifierNode($this->getCurrentToken()); $this->advance(1); // skip : @@ -190,17 +198,39 @@ class Parser $type = $this->parseType(); + $expression = null; + if ($this->getCurrentToken()->literal == "=") { + // skip = + $this->anticipateTokenAndSkip("="); + + $expression = $this->parseExpression( + shouldBeMap: $type instanceof MapTypeDeclaration, + shouldBeFunction: $type instanceof TypeDeclaration and $type->left->literal == "function", + ); + } + + return new ConstVariableDeclaration( + $identifier, + $type, + $expression, + ); + } + + private function parseVariableAssignment(): Node + { + $identifier = new IdentifierNode($this->getCurrentToken()); + $this->advance(1); + // skip = $this->anticipateTokenAndSkip("="); - + $expression = $this->parseExpression( - shouldBeMap: $type instanceof MapTypeDeclaration, - shouldBeFunction: $type instanceof TypeDeclaration and $type->left->literal == "function", + #shouldBeMap: $type instanceof MapTypeDeclaration, + #shouldBeFunction: $type instanceof TypeDeclaration and $type->left->literal == "function", ); - return new ConstVariableDeclaration( + return new VariableAssignment( $identifier, - $type, $expression, ); } @@ -291,6 +321,11 @@ class Parser $this->advance(1); } + else if ($currentToken->type == TokenType::PipePlaceholder) { + $currentExpression = new IdentifierNode($currentToken); + $this->advance(1); + } + else if ($currentToken->literal == "(") { if ($this->getNextToken(2)->literal == ":") { $currentExpression = $this->parseFunctionDefinition(); @@ -324,6 +359,10 @@ class Parser return new Condition($currentExpression, $nextToken, $this->parseExpression(shouldBeMap: $shouldBeMap)); } + else if ($nextToken->literal == "[") { + return $this->parseArrayOrMapAccess($currentExpression); + } + else if ($nextToken->literal == "=>") { $this->advance(1); @@ -419,6 +458,28 @@ class Parser } } + private function parseArrayOrMapAccess(Node $arrayOrMap): Node + { + $items = []; + + while ($this->getCurrentToken()->literal == "[") { + // skip current [ + $this->anticipateTokenAndSkip("["); + + $item = $this->parseExpression(); + + // skip last ] + $this->anticipateTokenAndSkip("]"); + + $items[] = $item; + } + + return new ArrayMapAccessNode( + $arrayOrMap, + $items, + ); + } + private function parseNumber(): Node { $currentToken = $this->getCurrentToken(); @@ -470,7 +531,7 @@ class Parser continue; } - $identifier = $this->getCurrentToken(); + $identifier = new IdentifierNode($this->getCurrentToken()); $this->advance(1); // skip : @@ -530,9 +591,14 @@ class Parser $this->advance(1); } - /*else if ($currentToken->type == TokenType::Identifier) { - $body[] = $this->parseFunctionCall(); - }*/ + else if ($currentToken->type == TokenType::Identifier) { + if ($this->getNextToken()->literal == "=") { + $body[] = $this->parseVariableAssignment(); + } + else { + $body[] = $this->parseFunctionCall(); + } + } else { $error = sprintf("Unexpected %s at %d:%d" . PHP_EOL, $currentToken->value, $currentToken->line, $currentToken->column); @@ -558,7 +624,7 @@ class Parser private function parseFunctionCall(): Node { - $identifier = $this->getCurrentToken(); + $identifier = new IdentifierNode($this->getCurrentToken()); $this->advance(1); // skip first ( @@ -590,7 +656,7 @@ class Parser // if "=" then identifier is name if ($this->getNextToken()->literal == "=") { - $identifier = $this->getCurrentToken(); + $identifier = new IdentifierNode($this->getCurrentToken()); $this->advance(2); $value = $this->parseExpression(); @@ -696,8 +762,16 @@ class Tree extends Node class ConstVariableDeclaration extends Node { public function __construct( - public Token $identifier, + public Node $identifier, public Node|Token $type, + public Node|Token|null $expression, + ) {} +} + +class VariableAssignment extends Node +{ + public function __construct( + public Node $identifier, public Node|Token $expression, ) {} } @@ -733,6 +807,11 @@ class ArrayNode extends Node public function __construct( public array $values, ) {} + + public function getValue(): array + { + return $this->values; + } } class MapNode extends Node @@ -743,7 +822,13 @@ class MapNode extends Node public function __construct( public array $values, ) {} + + public function getValue(): array + { + return $this->values; + } } + class MapItemNode extends Node { public function __construct( @@ -752,6 +837,17 @@ class MapItemNode extends Node ) {} } +class ArrayMapAccessNode extends Node +{ + public function __construct( + public ArrayNode|IdentifierNode $arrayOrMap, + /** + * @param Node[] $items + */ + public array $items, + ) {} +} + class OperatorExpression extends Node { public function __construct( @@ -792,6 +888,11 @@ class NumberNode extends Node public Token $token, public int|float $value, ) {} + + public function getValue(): int|float + { + return $this->value; + } } class StringNode extends Node @@ -799,6 +900,11 @@ class StringNode extends Node public function __construct( public Token $token, ) {} + + public function getValue(): string + { + return $this->token->value; + } } class BoolNode extends Node @@ -806,6 +912,11 @@ class BoolNode extends Node public function __construct( public Token $token, ) {} + + public function getValue(): bool + { + return filter_var($this->token->value, FILTER_VALIDATE_BOOLEAN); + } } class CommentNode extends Node @@ -822,7 +933,7 @@ class FunctionDefinition extends Node * @param FunctionDefinitionParameter[] $parameters */ public array $parameters, - public TypeDeclaration $returnType, + public TypeDeclaration|ArrayTypeDeclaration|MapTypeDeclaration $returnType, /** * @param Node[] $body */ @@ -833,8 +944,8 @@ class FunctionDefinition extends Node class FunctionDefinitionParameter extends Node { public function __construct( - public Token $identifier, - public TypeDeclaration $type, + public Node $identifier, + public TypeDeclaration|ArrayTypeDeclaration|MapTypeDeclaration $type, public ?Node $defaultValue = null, ) {} } @@ -849,7 +960,7 @@ class FunctionReturn extends Node class FunctionCall extends Node { public function __construct( - public Token $identifier, + public Node $identifier, /** * @param FunctionCallParameter[] $parameters */ @@ -860,7 +971,7 @@ class FunctionCall extends Node class FunctionCallParameter extends Node { public function __construct( - public ?Token $identifier, + public ?Node $identifier, public Node|Token $value, ) {} } |