Today's goal was to wrap up parsing of attributes in the Forte parser. In a previous blog post, I discussed how I've relaxed the HTML parser, which enables me to unify HTML tags, Blade components, Livewire components, Flux components, and more. This simplifies a few things, as I can have one parsing routine for attributes; however, there still exists some complexity to consider from a parsing and AST perspective.
Basic HTML attributes are simple to parse:
1<div class="mt-2">
2 ...
3</div>
The tokenizer emits a name, some tokens for the equals sign, the quote, and a few more, the value, and the end quote. That's pretty simple to deal with.
#More Complicated Attributes
The following types of templates get a bit more challenging:
1<div
2 class="mt-2"
3 :class="{}"
4 :$bound
5 :dynamic="var"
6 ::escaped="thing"
7 data-attribute
8 {{ $name }}
9 data-{{ $value }}="value"
10 data-{{ $value }}-thing="{{ $thing }}"
11 data={{ $thing1 }}
12 {{ $thing2 }}={{ $anotherThing }}
13>
14 <p>Inner content.</p>
15</div>
The parser will work to make sense of this and produce a usable AST. Whenever we have attributes like the following, the parser creates an InterpolatedAttributeNode
, with all the various components of both the name and value broken out for us.
1data-{{ $value }}-thing="{{ $thing }}"
The whole AST for the original example is as follows:
Parsing attributes can get even more complicated with:
1<div
2 {{ 'data-' }}<?php echo 'attribute'; ?>-name-@if(true != false)-part-@endif=<?php echo 'thing'; ?>
3>
4 <p>Inner content.</p>
5</div>
We can look at that and say "people shouldn't do that!", and I agree, but since it's technically possible, the parser needs to be able to handle it. Additionally, if we ever wanted to write an analyzer to inform people that they shouldn't do things like that. In that case, we need to be able to parse it anyway.
Here is what Forte produces for that template:
If you'd like me to provide more details about how this works, please let me know! I'm going to call it a day as my brain needs some downtime after working through all of this.
∎