diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon
index dad26168..147d86f8 100644
--- a/phpstan-baseline.neon
+++ b/phpstan-baseline.neon
@@ -1052,7 +1052,7 @@ parameters:
-
message: "#^Parameter \\#1 \\$str of static method PhpMyAdmin\\\\SqlParser\\\\Context\\:\\:isSeparator\\(\\) expects string, mixed given\\.$#"
- count: 4
+ count: 7
path: src/Lexer.php
-
diff --git a/psalm-baseline.xml b/psalm-baseline.xml
index c87d9b3d..2c9351da 100644
--- a/psalm-baseline.xml
+++ b/psalm-baseline.xml
@@ -695,21 +695,14 @@
$this->last
$this->last
-
- $this->str[$this->last + 1]
- $this->str[$this->last++]
- $this->str[$this->last]
- $this->str[$this->last]
- $this->str[$this->last]
- $this->str[$this->last]
- $this->str[$this->last]
- $this->str[$this->last]
- $this->str[$this->last]
- $this->str[$this->last]
- $this->str[$this->last]
+
$this->str[$this->last]
$this->str[$this->last]
$this->str[$this->last]
+
+
+ $this->str[$this->last + 1]
+ $this->str[$this->last++]
$this->str[$this->last]
$this->str[$this->last]
$this->str[$this->last]
diff --git a/src/Lexer.php b/src/Lexer.php
index 0e34bc38..a5063dbe 100644
--- a/src/Lexer.php
+++ b/src/Lexer.php
@@ -842,7 +842,7 @@ public function parseNumber()
// or "E" causing wrongly interpreted scientific notation (".e[0 to 9]" is invalid). Such invalid notation could
// break the lexer when table names under a given database context starts with ".e[0-9]".
//
- // Valid final states are: 2, 3, 4 and 6. Any parsing that finished in a
+ // Valid final states are: 2, 3, 4, 6, and 9. Any parsing that finished in a
// state other than these is invalid.
// Also, negative states are invalid states.
$iBak = $this->last;
@@ -886,14 +886,12 @@ public function parseNumber()
$state = 4;
} elseif ($this->str[$this->last] === 'e' || $this->str[$this->last] === 'E') {
$state = 5;
- } elseif (
- ($this->str[$this->last] >= 'a' && $this->str[$this->last] <= 'z')
- || ($this->str[$this->last] >= 'A' && $this->str[$this->last] <= 'Z')
- ) {
- // A number can't be directly followed by a letter
- $state = -$state;
- break;
} elseif ($this->str[$this->last] < '0' || $this->str[$this->last] > '9') {
+ if (! Context::isSeparator($this->str[$this->last])) {
+ // A number can't be directly followed by a letter _ or $
+ $state = -$state;
+ }
+
// Just digits and `.`, `e` and `E` are valid characters.
break;
}
@@ -901,14 +899,12 @@ public function parseNumber()
$flags |= Token::FLAG_NUMBER_FLOAT;
if ($this->str[$this->last] === 'e' || $this->str[$this->last] === 'E') {
$state = 5;
- } elseif (
- ($this->str[$this->last] >= 'a' && $this->str[$this->last] <= 'z')
- || ($this->str[$this->last] >= 'A' && $this->str[$this->last] <= 'Z')
- ) {
- // A number can't be directly followed by a letter
- $state = -$state;
- break;
} elseif ($this->str[$this->last] < '0' || $this->str[$this->last] > '9') {
+ if (! Context::isSeparator($this->str[$this->last])) {
+ // A number can't be directly followed by a letter _ or $
+ $state = -$state;
+ }
+
// Just digits, `e` and `E` are valid characters.
break;
}
@@ -919,14 +915,12 @@ public function parseNumber()
|| ($this->str[$this->last] >= '0' && $this->str[$this->last] <= '9')
) {
$state = 6;
- } elseif (
- ($this->str[$this->last] >= 'a' && $this->str[$this->last] <= 'z')
- || ($this->str[$this->last] >= 'A' && $this->str[$this->last] <= 'Z')
- ) {
- // A number can't be directly followed by a letter
- $state = -$state;
- break;
} else {
+ if (! Context::isSeparator($this->str[$this->last])) {
+ // A number can't be directly followed by a letter _ or $
+ $state = -$state;
+ }
+
break;
}
} elseif ($state === 6) {
diff --git a/tests/Lexer/LexerTest.php b/tests/Lexer/LexerTest.php
index e310c94f..02eddf62 100644
--- a/tests/Lexer/LexerTest.php
+++ b/tests/Lexer/LexerTest.php
@@ -76,6 +76,7 @@ public static function lexProvider(): array
['lexer/lexKeyword'],
['lexer/lexKeyword2'],
['lexer/lexNumber'],
+ ['lexer/lexNumberAtStartOfName'],
['lexer/lexOperator'],
['lexer/lexOperatorStarIsArithmetic'],
['lexer/lexOperatorStarIsWildcard'],
diff --git a/tests/data/lexer/lexNumberAtStartOfName.in b/tests/data/lexer/lexNumberAtStartOfName.in
new file mode 100644
index 00000000..f068ab6c
--- /dev/null
+++ b/tests/data/lexer/lexNumberAtStartOfName.in
@@ -0,0 +1 @@
+INSERT INTO 2_bar SELECT 1;
\ No newline at end of file
diff --git a/tests/data/lexer/lexNumberAtStartOfName.out b/tests/data/lexer/lexNumberAtStartOfName.out
new file mode 100644
index 00000000..29e6cd3d
--- /dev/null
+++ b/tests/data/lexer/lexNumberAtStartOfName.out
@@ -0,0 +1,124 @@
+{
+ "query": "INSERT INTO 2_bar SELECT 1;",
+ "lexer": {
+ "@type": "PhpMyAdmin\\SqlParser\\Lexer",
+ "str": "INSERT INTO 2_bar SELECT 1;",
+ "len": 27,
+ "last": 27,
+ "list": {
+ "@type": "PhpMyAdmin\\SqlParser\\TokensList",
+ "tokens": [
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": "INSERT",
+ "value": "INSERT",
+ "keyword": "INSERT",
+ "type": 1,
+ "flags": 35,
+ "position": 0
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": " ",
+ "value": " ",
+ "keyword": null,
+ "type": 3,
+ "flags": 0,
+ "position": 6
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": "INTO",
+ "value": "INTO",
+ "keyword": "INTO",
+ "type": 1,
+ "flags": 3,
+ "position": 7
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": " ",
+ "value": " ",
+ "keyword": null,
+ "type": 3,
+ "flags": 0,
+ "position": 11
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": "2_bar",
+ "value": "2_bar",
+ "keyword": null,
+ "type": 0,
+ "flags": 0,
+ "position": 12
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": " ",
+ "value": " ",
+ "keyword": null,
+ "type": 3,
+ "flags": 0,
+ "position": 17
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": "SELECT",
+ "value": "SELECT",
+ "keyword": "SELECT",
+ "type": 1,
+ "flags": 3,
+ "position": 18
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": " ",
+ "value": " ",
+ "keyword": null,
+ "type": 3,
+ "flags": 0,
+ "position": 24
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": "1",
+ "value": 1,
+ "keyword": null,
+ "type": 6,
+ "flags": 0,
+ "position": 25
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": ";",
+ "value": ";",
+ "keyword": null,
+ "type": 9,
+ "flags": 0,
+ "position": 26
+ },
+ {
+ "@type": "PhpMyAdmin\\SqlParser\\Token",
+ "token": null,
+ "value": null,
+ "keyword": null,
+ "type": 9,
+ "flags": 0,
+ "position": null
+ }
+ ],
+ "count": 11,
+ "idx": 0
+ },
+ "delimiter": ";",
+ "delimiterLen": 1,
+ "strict": false,
+ "errors": []
+ },
+ "parser": null,
+ "errors": {
+ "lexer": [],
+ "parser": []
+ }
+}
\ No newline at end of file