Skip to content

Commit 4d9b9d2

Browse files
committed
add test for lexer
1 parent 06d077d commit 4d9b9d2

File tree

2 files changed

+64
-11
lines changed

2 files changed

+64
-11
lines changed

classes/local/lexer.php

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -471,17 +471,9 @@ private function read_empty_token(): token {
471471
// Record position of the $ symbol.
472472
$startingposition = $this->inputstream->get_position();
473473

474-
while ($currentchar !== input_stream::EOF) {
475-
$nextchar = $this->inputstream->peek();
476-
// Identifiers may contain letters, digits or underscores.
477-
if (!preg_match('/[EMPTY]/', $nextchar)) {
478-
break;
479-
}
480-
$currentchar = $this->inputstream->read();
481-
$result .= $currentchar;
482-
}
483-
if ($result === '$EMPTY') {
484-
return new token(token::EMPTY, $result, $startingposition['row'], $startingposition['column']);
474+
$identifier = $this->read_identifier();
475+
if ($identifier->value === 'EMPTY') {
476+
return new token(token::EMPTY, '$EMPTY', $startingposition['row'], $startingposition['column']);
485477
}
486478

487479
$this->inputstream->die(get_string('error_invalid_dollar', 'qtype_formulas'));

tests/lexer_test.php

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,67 @@ public function test_get_token_list_7(): void {
426426
}
427427
}
428428

429+
/**
430+
* Data provider. The test will assume the input starts with 'a =' and will automatically check for
431+
* the 'a' (IDENTIFIER) and '=' (OPERATOR) token. For invalid input, we use the string of the expected
432+
* error message.
433+
*
434+
* @return array
435+
*/
436+
public static function provide_inputs_with_empty(): array {
437+
$string = new token(token::STRING, '$EMPTY');
438+
$empty = new token(token::EMPTY, '$EMPTY');
439+
$plus = new token(token::OPERATOR, '+');
440+
$errormessage = 'Invalid use of the dollar ($) symbol. It can only be used for the special value $EMPTY.';
441+
return [
442+
[[$empty], 'a = $EMPTY'],
443+
[[$string], 'a = "$EMPTY"'],
444+
[[$string], "a = '\$EMPTY'"],
445+
[[$empty, $plus], 'a = $EMPTY+'],
446+
["Unexpected input: '.'", 'a = $EMPTY.'],
447+
[$errormessage, 'a = $EMPT'],
448+
[$errormessage, 'a = $EMPTYness'],
449+
];
450+
}
451+
452+
/**
453+
* Test whether lexing of the special $EMPTY token works as expected.
454+
*
455+
* @param array|string $expected array of tokens after the 'a =' part or expected error message
456+
* @param string $input the input to be parsed
457+
* @return void
458+
*
459+
* @dataProvider provide_inputs_with_empty
460+
*/
461+
public function test_get_token_list_with_empty_token($expected, $input): void {
462+
$error = '';
463+
try {
464+
$lexer = new lexer($input);
465+
} catch (Exception $e) {
466+
$error = $e->getMessage();
467+
}
468+
469+
// If we expect an error, check the error message.
470+
if (is_string($expected)) {
471+
self::assertStringEndsWith($expected, $error);
472+
return;
473+
}
474+
475+
// We did not expect an error. Check there was none and verify we got the right tokens.
476+
self::assertEmpty($error);
477+
$expectedlist = [
478+
new token(token::IDENTIFIER, 'a'),
479+
new token(token::OPERATOR, '='),
480+
];
481+
$expectedlist = $expectedlist + $expected;
482+
483+
$tokens = $lexer->get_tokens();
484+
foreach ($expectedlist as $i => $token) {
485+
self::assertEquals($token->type, $tokens[$i]->type);
486+
self::assertEquals($token->value, $tokens[$i]->value);
487+
}
488+
}
489+
429490
public function test_get_token_list_with_subsequent_comments(): void {
430491
$input = <<<EOF
431492
# First comment

0 commit comments

Comments
 (0)