Skip to content

Commit

Permalink
TASK: Parse negative integer literals
Browse files Browse the repository at this point in the history
  • Loading branch information
grebaldi committed Aug 18, 2023
1 parent dcbf92f commit d7e1799
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 2 deletions.
2 changes: 2 additions & 0 deletions src/Language/Parser/Expression/ExpressionParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ final class ExpressionParser
Rule::KEYWORD_NULL,
Rule::KEYWORD_MATCH,
Rule::STRING_LITERAL_DELIMITER,
Rule::SYMBOL_DASH,
Rule::INTEGER_HEXADECIMAL,
Rule::INTEGER_DECIMAL,
Rule::INTEGER_OCTAL,
Expand Down Expand Up @@ -154,6 +155,7 @@ private function parseUnaryStatement(Lexer $lexer): ExpressionNode
$this->parseNullLiteral($lexer),
Rule::STRING_LITERAL_DELIMITER =>
$this->parseStringLiteral($lexer),
Rule::SYMBOL_DASH,
Rule::INTEGER_HEXADECIMAL,
Rule::INTEGER_DECIMAL,
Rule::INTEGER_OCTAL,
Expand Down
14 changes: 12 additions & 2 deletions src/Language/Parser/IntegerLiteral/IntegerLiteralParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,22 @@ final class IntegerLiteralParser
public function parse(Lexer $lexer): IntegerLiteralNode
{
try {
$start = null;
$value = '';

if ($lexer->probe(Rule::SYMBOL_DASH)) {
$start = $lexer->buffer->getStart();
$value = $lexer->buffer->getContents();
}

$rule = $lexer->read(...self::RULES_INTEGER_FORMATS);
$start ??= $lexer->buffer->getStart();
$value .= $lexer->buffer->getContents();

return new IntegerLiteralNode(
rangeInSource: $lexer->buffer->getRange(),
rangeInSource: $start->toRange($lexer->buffer->getEnd()),
format: $this->getIntegerFormatFromToken($rule),
value: $lexer->buffer->getContents()
value: $value
);
} catch (LexerException $e) {
throw IntegerLiteralCouldNotBeParsed::becauseOfLexerException($e);
Expand Down
92 changes: 92 additions & 0 deletions test/Unit/Language/Parser/Expression/ExpressionParserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -881,6 +881,29 @@ public function parsesBinaryIntegerLiteral(): void
);
}

/**
* @test
*/
public function parsesNegativeBinaryIntegerLiteral(): void
{
$expressionParser = new ExpressionParser();
$lexer = new Lexer('-0b1001');

$expectedExpressioNode = new ExpressionNode(
rangeInSource: $this->range([0, 0], [0, 6]),
root: new IntegerLiteralNode(
rangeInSource: $this->range([0, 0], [0, 6]),
format: IntegerFormat::BINARY,
value: '-0b1001'
)
);

$this->assertEquals(
$expectedExpressioNode,
$expressionParser->parse($lexer)
);
}

/**
* @test
*/
Expand All @@ -904,6 +927,29 @@ public function parsesOctalIntegerLiteral(): void
);
}

/**
* @test
*/
public function parsesNegativeOctalIntegerLiteral(): void
{
$expressionParser = new ExpressionParser();
$lexer = new Lexer('-0o755');

$expectedExpressioNode = new ExpressionNode(
rangeInSource: $this->range([0, 0], [0, 5]),
root: new IntegerLiteralNode(
rangeInSource: $this->range([0, 0], [0, 5]),
format: IntegerFormat::OCTAL,
value: '-0o755'
)
);

$this->assertEquals(
$expectedExpressioNode,
$expressionParser->parse($lexer)
);
}

/**
* @test
*/
Expand All @@ -927,6 +973,29 @@ public function parsesDecimalIntegerLiteral(): void
);
}

/**
* @test
*/
public function parsesNegativeDecimalIntegerLiteral(): void
{
$expressionParser = new ExpressionParser();
$lexer = new Lexer('-42');

$expectedExpressioNode = new ExpressionNode(
rangeInSource: $this->range([0, 0], [0, 2]),
root: new IntegerLiteralNode(
rangeInSource: $this->range([0, 0], [0, 2]),
format: IntegerFormat::DECIMAL,
value: '-42'
)
);

$this->assertEquals(
$expectedExpressioNode,
$expressionParser->parse($lexer)
);
}

/**
* @test
*/
Expand All @@ -950,6 +1019,29 @@ public function parsesHexadecimalIntegerLiteral(): void
);
}

/**
* @test
*/
public function parsesNegativeHexadecimalIntegerLiteral(): void
{
$expressionParser = new ExpressionParser();
$lexer = new Lexer('-0xABC');

$expectedExpressioNode = new ExpressionNode(
rangeInSource: $this->range([0, 0], [0, 5]),
root: new IntegerLiteralNode(
rangeInSource: $this->range([0, 0], [0, 5]),
format: IntegerFormat::HEXADECIMAL,
value: '-0xABC'
)
);

$this->assertEquals(
$expectedExpressioNode,
$expressionParser->parse($lexer)
);
}

/**
* @test
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,26 @@ public function parsesBinaryInteger(): void
);
}

/**
* @test
*/
public function parsesNegativeBinaryInteger(): void
{
$integerLiteralParser = IntegerLiteralParser::singleton();
$lexer = new Lexer('-0b1010110101');

$expectedIntegerLiteralNode = new IntegerLiteralNode(
rangeInSource: $this->range([0, 0], [0, 12]),
format: IntegerFormat::BINARY,
value: '-0b1010110101'
);

$this->assertEquals(
$expectedIntegerLiteralNode,
$integerLiteralParser->parse($lexer)
);
}

/**
* @test
*/
Expand All @@ -73,6 +93,26 @@ public function parsesOctalInteger(): void
);
}

/**
* @test
*/
public function parsesNegativeOctalInteger(): void
{
$integerLiteralParser = IntegerLiteralParser::singleton();
$lexer = new Lexer('-0o755');

$expectedIntegerLiteralNode = new IntegerLiteralNode(
rangeInSource: $this->range([0, 0], [0, 5]),
format: IntegerFormat::OCTAL,
value: '-0o755'
);

$this->assertEquals(
$expectedIntegerLiteralNode,
$integerLiteralParser->parse($lexer)
);
}

/**
* @test
*/
Expand All @@ -93,6 +133,26 @@ public function parsesDecimalInteger(): void
);
}

/**
* @test
*/
public function parsesNegativeDecimalInteger(): void
{
$integerLiteralParser = IntegerLiteralParser::singleton();
$lexer = new Lexer('-1234567890');

$expectedIntegerLiteralNode = new IntegerLiteralNode(
rangeInSource: $this->range([0, 0], [0, 10]),
format: IntegerFormat::DECIMAL,
value: '-1234567890'
);

$this->assertEquals(
$expectedIntegerLiteralNode,
$integerLiteralParser->parse($lexer)
);
}

/**
* @test
*/
Expand All @@ -113,6 +173,26 @@ public function parsesHexadecimalInteger(): void
);
}

/**
* @test
*/
public function parsesNegativeHexadecimalInteger(): void
{
$integerLiteralParser = IntegerLiteralParser::singleton();
$lexer = new Lexer('-0x123456789ABCDEF');

$expectedIntegerLiteralNode = new IntegerLiteralNode(
rangeInSource: $this->range([0, 0], [0, 17]),
format: IntegerFormat::HEXADECIMAL,
value: '-0x123456789ABCDEF'
);

$this->assertEquals(
$expectedIntegerLiteralNode,
$integerLiteralParser->parse($lexer)
);
}

/**
* @test
*/
Expand Down

0 comments on commit d7e1799

Please sign in to comment.