Skip to content

Commit

Permalink
[DOCS] Document TypoScript parse edge case behavior
Browse files Browse the repository at this point in the history
The TypoScript parser matches valid operators
first before dealing with values.
Therefore, the TS `foo =<something` is now
considered a reference and not an assignment.

Resolves: #102101
Releases: main, 12.4
Change-Id: I7014b92f7a9120d0e77d264e964adef9d062070c
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/81357
Reviewed-by: Christian Kuhn <lolli@schwarzbu.ch>
Tested-by: core-ci <typo3@b13.com>
Tested-by: Christian Kuhn <lolli@schwarzbu.ch>
  • Loading branch information
liayn authored and lolli42 committed Oct 6, 2023
1 parent 42e7ea6 commit a39dffb
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 3 deletions.
Expand Up @@ -261,4 +261,29 @@ used "\\r" as single linebreak character. This old linebreak type is no longer d
when parsing TypoScript and may lead to funny results, but chances are very low any
instance is affected by this.

Operator matching has higher precedence
---------------------------------------

The new parser looks for valid operators first, then parses things behind it.
Consider this example:

.. code-block:: typoscript
lib.nav.wrap =<ul id="nav">|</ul>
This is ambiguous: The above :typoscript:`=<ul` could be interpreted both as an
assignment :typoscript:`=` of the value :typoscript:`<ul`, or as a reference
:typoscript:`=<` to the identifier :typoscript:`ul`.

While the old parser interpreted this as an assignment, the new parser treats it
as a reference.

The above example aims for an assignment, though, which can be achieved by adding
a whitespace between :typoscript:`=` and :typoscript:`<`:

.. code-block:: typoscript
lib.nav.wrap = <ul id="nav">|</ul>
.. index:: Backend, Frontend, TSConfig, TypoScript, NotScanned, ext:core
Expand Up @@ -387,7 +387,7 @@ public static function tokenizeStringDataProvider(): array
)
),
],
'identifier, assignment, value with whitespaces' => [
'identifier, assignment, whitespace, value' => [
'foo = bar',
(new LineStream())
->append(
Expand Down Expand Up @@ -422,6 +422,41 @@ public static function tokenizeStringDataProvider(): array
)
),
],
'identifier, assignment, whitespace, value with < is considered an assignment line, not a reference' => [
'foo = <bar',
(new LineStream())
->append(
(new IdentifierAssignmentLine())
->setTokenStream(
(new TokenStream())
->append(new IdentifierToken(TokenType::T_IDENTIFIER, 'foo', 0, 0))
->append(new Token(TokenType::T_BLANK, ' ', 0, 3))
->append(new Token(TokenType::T_OPERATOR_ASSIGNMENT, '=', 0, 4))
->append(new Token(TokenType::T_BLANK, ' ', 0, 5))
->append(new Token(TokenType::T_VALUE, '<bar', 0, 6)),
)
->setIdentifierTokenStream(
(new IdentifierTokenStream())
->append(new IdentifierToken(TokenType::T_IDENTIFIER, 'foo', 0, 0))
)
->setValueTokenStream(
(new TokenStream())
->append(new Token(TokenType::T_VALUE, '<bar', 0, 6))
)
),
(new LineStream())
->append(
(new IdentifierAssignmentLine())
->setIdentifierTokenStream(
(new IdentifierTokenStream())
->append(new IdentifierToken(TokenType::T_IDENTIFIER, 'foo'))
)
->setValueTokenStream(
(new TokenStream())
->append(new Token(TokenType::T_VALUE, '<bar'))
)
),
],
'identifier with colon, assignment, value with whitespaces' => [
'foo:bar = fooValue',
(new LineStream())
Expand Down Expand Up @@ -1731,7 +1766,7 @@ public static function tokenizeStringDataProvider(): array
)
),
],
'identifier, reference, identifiers with whitespaces' => [
'identifier, reference, whitespace, identifiers' => [
'foo =< bar1.bar2',
(new LineStream())
->append(
Expand Down Expand Up @@ -1770,7 +1805,7 @@ public static function tokenizeStringDataProvider(): array
)
),
],
'identifier, reference, relative identifiers with whitespaces' => [
'identifier, reference, whitespace, relative identifiers' => [
'foo =< .bar1.bar2',
(new LineStream())
->append(
Expand Down

0 comments on commit a39dffb

Please sign in to comment.