Skip to content

Instantly share code, notes, and snippets.

@fre-sch
Last active August 27, 2022 09:21
Show Gist options
  • Save fre-sch/8661d32a15e01b4edb5350efbf15cfd3 to your computer and use it in GitHub Desktop.
Save fre-sch/8661d32a15e01b4edb5350efbf15cfd3 to your computer and use it in GitHub Desktop.
parser for alternative syntax to use preact h
@{%
// Moo lexer documention is here:
// https://github.com/no-context/moo
const moo = require("moo")
const lexer = moo.compile({
ws: {match: /\s+/, lineBreaks: true},
literal_id: {
match: /#[a-zA-Z_-][a-zA-Z_0-9_-]*/,
value: s => s.slice(1)
},
literal_cls: {
match: /\.[a-zA-Z_-][a-zA-Z0-9_-]*/,
value: s => s.slice(1)
},
literal: /[a-zA-Z_-][a-zA-Z0-9_-]*/,
equal: '=',
paren_start: '(',
paren_end: ')',
string: /"(?:\\["bfnrt\/\\]|\\u[a-fA-F0-9]{4}|[^"\\])*"/
});
const el = (type="div", props={}, children=[]) => ({type, props, children})
const ofe = Object.fromEntries
%}
@lexer lexer
main -> el_tail {% id %}
el -> PS el_head __ el_tail _ PE {% d => el(d[1][0], ofe(d[1][1]), d[3]) %}
el_no_tail -> PS el_head _ PE {% d => el(d[1][0]) %}
el_attrs -> PS el_head __ attr_pairs __ el_tail _ PE {% d => el(d[1][0], ofe([ ...d[1][1], ...d[3] ]), d[5]) %}
el_tail -> null | el_children {% id %}
el_children -> el_child el_child_sep:* {% d => [ d[0], ...d[1] ] %}
el_child_sep -> _ el_child {% d => d[1] %}
el_child -> (string | el_attrs | el_no_tail | el) {% d => d[0][0] %}
el_head -> tag_name {% d => [ d[0], [] ] %}
| tag_name tag_id {% d => [ d[0], [d[1],] ] %}
| tag_name tag_id tag_classlist {% d => [ d[0], [ d[1], d[2] ] ] %}
| tag_name tag_classlist {% d => [ d[0], [ d[1] ] ] %}
| tag_id {% d => [ "div", d[0] ] %}
| tag_id tag_classlist {% d => [ "div", [ d[0], d[1] ] ] %}
| tag_classlist {% d => [ "div", d[0] ] %}
tag_name -> %literal {% d => d[0].value %}
tag_classlist -> tag_class:+ {% d => ["class", d[0].join(" ")] %}
tag_class -> %literal_cls {% d => d[0].value %}
tag_id -> %literal_id {% d => ["id", d[0].value] %}
attr_pairs -> attr_pair attr_pairs_tail:* {% d => [d[0], ...d[1]] %}
attr_pairs_tail -> __ attr_pair {% d => d[1] %}
attr_pair -> attr_key equal string {% d => [d[0], d[2]] %}
attr_key -> %literal {% d => d[0].value %}
string -> %string {% d => JSON.parse(d[0].value) %}
PS -> %paren_start {% d => null %}
PE -> %paren_end {% d => null %}
equal -> %equal {% d => null %}
__ -> %ws {% d => null %}
_ -> %ws:* {% d => null %}
(nav#main.navbar.bg-dark data-route="#foobar"
(ul
(li.nav-item "one")
(li.nav-item "two")
(li.nav-item.active "three")
)
)
{
"type": "nav",
"props": {
"id": "main",
"class": "navbar bg-dark",
"data-route": "#foobar"
},
"children": [
{
"type": "ul",
"props": {},
"children": [
{
"type": "li",
"props": {
"class": "nav-item"
},
"children": [
"one"
]
},
{
"type": "li",
"props": {
"class": "nav-item"
},
"children": [
"two"
]
},
{
"type": "li",
"props": {
"class": "nav-item active"
},
"children": [
"three"
]
}
]
}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment