@ohm-js/wasm 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,605 @@
1
+ Helpers {
2
+ Node = (spaces TextNode)* spaces
3
+ TextNode = spaces AnyExceptPlus<openControl>
4
+ openControl = end
5
+
6
+ empty = /* nothing */
7
+ anyExcept<lit> = (~ lit any)
8
+ anyExceptStar<lit> = (~ lit any)*
9
+ anyExceptPlus<lit> = (~ lit any)+
10
+ AnyExcept<lit> = (spaces ~ lit any)
11
+ AnyExceptPlus<lit> = (spaces ~ lit any)+
12
+ AnyExceptStar<lit> = (spaces ~ lit any)*
13
+ identifierCharacter = alnum | "_" | "-"
14
+
15
+ orderedListOf<a, b, sep> =
16
+ | nonemptyOrderedListOf<a, b, sep>
17
+ | emptyListOf<a, sep>
18
+ nonemptyOrderedListOf<a, b, sep> =
19
+ | nonemptyListOf<b, sep>
20
+ | nonemptyOrderedListOfBoth<a, b, sep>
21
+ | nonemptyListOf<a, sep>
22
+ nonemptyOrderedListOfBoth<a, b, sep> =
23
+ nonemptyListOf<a, sep> (sep nonemptyListOf<b, sep>)
24
+
25
+ singleQuote = "'" | "‘" | "’"
26
+ doubleQuote = "\"" | "“" | "”"
27
+ controls = "\u{007F}".."\u{009F}"
28
+ noncharacters = "\u{FDD0}".."\u{FDEF}"
29
+ newline = "\r"? "\n"
30
+ }
31
+
32
+ Liquid <: Helpers {
33
+ Node := (spaces (liquidNode | TextNode))*
34
+ openControl := "{{" | "{%"
35
+ endOfTagName = &("-%}" | "-}}" | "%}" | "}}")
36
+ endOfVarName = ~identifierCharacter
37
+ endOfIdentifier = endOfTagName | endOfVarName
38
+
39
+ liquidNode =
40
+ | liquidDoc
41
+ | liquidBlockComment
42
+ | liquidRawTag
43
+ | liquidDrop
44
+ | liquidTagClose
45
+ | liquidTagOpen
46
+ | liquidTag
47
+ | liquidInlineComment
48
+
49
+ liquidTagStrict =
50
+ | liquidTagAssign
51
+ | liquidTagBreak
52
+ | liquidTagContinue
53
+ | liquidTagCycle
54
+ | liquidTagContentFor
55
+ | liquidTagDecrement
56
+ | liquidTagEcho
57
+ | liquidTagElse
58
+ | liquidTagElsif
59
+ | liquidTagInclude
60
+ | liquidTagIncrement
61
+ | liquidTagLayout
62
+ | liquidTagLiquid
63
+ | liquidTagRender
64
+ | liquidTagSection
65
+ | liquidTagSections
66
+ | liquidTagWhen
67
+
68
+ liquidTag =
69
+ | liquidTagStrict
70
+ | liquidTagBaseCase
71
+
72
+ liquidTagOpenStrict =
73
+ | liquidTagOpenCase
74
+ | liquidTagOpenCapture
75
+ | liquidTagOpenForm
76
+ | liquidTagOpenFor
77
+ | liquidTagOpenTablerow
78
+ | liquidTagOpenIf
79
+ | liquidTagOpenPaginate
80
+ | liquidTagOpenUnless
81
+
82
+ liquidTagOpen =
83
+ | liquidTagOpenStrict
84
+ | liquidTagOpenBaseCase
85
+
86
+ liquidTagClose = "{%" "-"? space* "end" blockName space* tagMarkup "-"? "%}"
87
+
88
+ // These two are the same but transformed differently
89
+ liquidTagRule<name, markup> =
90
+ "{%" "-"? space* (name endOfIdentifier) space* markup "-"? "%}"
91
+ liquidTagOpenRule<name, markup> =
92
+ "{%" "-"? space* (name endOfIdentifier) space* markup "-"? "%}"
93
+
94
+ liquidTagBaseCase = liquidTagRule<liquidTagName, tagMarkup>
95
+
96
+ liquidTagEcho = liquidTagRule<"echo", liquidTagEchoMarkup>
97
+ liquidTagEchoMarkup = liquidVariable<delimTag>
98
+
99
+ liquidTagAssign = liquidTagRule<"assign", liquidTagAssignMarkup>
100
+ liquidTagAssignMarkup = variableSegment space* "=" space* liquidVariable<delimTag>
101
+
102
+ liquidTagCycle = liquidTagRule<"cycle", liquidTagCycleMarkup>
103
+ liquidTagCycleMarkup = (liquidExpression<delimTag> ":")? space* nonemptyListOf<liquidExpression<delimTag>, argumentSeparator> space*
104
+
105
+ liquidTagIncrement = liquidTagRule<"increment", variableSegmentAsLookupMarkup>
106
+ liquidTagDecrement = liquidTagRule<"decrement", variableSegmentAsLookupMarkup>
107
+ liquidTagOpenCapture = liquidTagOpenRule<"capture", variableSegmentAsLookupMarkup>
108
+ variableSegmentAsLookupMarkup = variableSegmentAsLookup space*
109
+
110
+ liquidTagSection = liquidTagRule<"section", liquidTagSectionMarkup>
111
+ liquidTagSectionMarkup = liquidString<delimTag> space*
112
+
113
+ liquidTagSections = liquidTagRule<"sections", liquidTagSectionsMarkup>
114
+ liquidTagSectionsMarkup = liquidString<delimTag> space*
115
+
116
+ liquidTagLayout = liquidTagRule<"layout", liquidTagLayoutMarkup>
117
+ liquidTagLayoutMarkup = liquidExpression<delimTag> space*
118
+
119
+ // We'll black hole the statement and switch parser in the cst builder
120
+ // We do this because it's technically the same grammar (with minor redefinitions)
121
+ // and it would be a huge chore and maintenance hell to rewrite all the rules with
122
+ // hspace = " " | "\t"
123
+ //
124
+ // The alternative is that this grammar parses the {% liquid tagMarkup %} as its own string,
125
+ // and then we switch to the LiquidStatement grammar that
126
+ // redefines liquidTagOpenRule, liquidTagRule, and space.
127
+ liquidTagLiquid = liquidTagRule<"liquid", liquidTagLiquidMarkup>
128
+ liquidTagLiquidMarkup = tagMarkup
129
+
130
+ liquidTagContentFor = liquidTagRule<"content_for", liquidTagContentForMarkup>
131
+
132
+ liquidTagContentForMarkup =
133
+ contentForType (argumentSeparatorOptionalComma contentForTagArgument) (space* ",")? space*
134
+
135
+ contentForTagArgument = listOf<contentForNamedArgument<delimTag>, argumentSeparatorOptionalComma>
136
+ completionModeContentForTagArgument = listOf<contentForNamedArgument<delimTag>, argumentSeparatorOptionalComma> (argumentSeparator? (liquidVariableLookup<delimTag>))?
137
+ contentForNamedArgument<delim> = (variableSegment ("." variableSegment)*) space* ":" space* (liquidExpression<delim>)
138
+
139
+ contentForType = liquidString<delimTag>
140
+
141
+ liquidTagInclude = liquidTagRule<"include", liquidTagRenderMarkup>
142
+ liquidTagRender = liquidTagRule<"render", liquidTagRenderMarkup>
143
+ liquidTagRenderMarkup =
144
+ snippetExpression renderVariableExpression? renderAliasExpression? renderArguments
145
+
146
+ renderArguments = (argumentSeparatorOptionalComma tagArguments) (space* ",")? space*
147
+ completionModeRenderArguments = (argumentSeparatorOptionalComma tagArguments) (space* ",")? space* (argumentSeparator? liquidVariableLookup<delimTag> space*)?
148
+ snippetExpression = liquidString<delimTag> | variableSegmentAsLookup
149
+ renderVariableExpression = space+ ("for" | "with") space+ liquidExpression<delimTag>
150
+ renderAliasExpression = space+ "as" space+ variableSegment
151
+
152
+ liquidTagOpenBaseCase = liquidTagOpenRule<blockName, tagMarkup>
153
+
154
+ liquidTagOpenForm = liquidTagOpenRule<"form", liquidTagOpenFormMarkup>
155
+ liquidTagOpenFormMarkup = arguments<delimTag> (space* ",")? space*
156
+
157
+ liquidTagOpenFor = liquidTagOpenRule<"for", liquidTagOpenForMarkup>
158
+ liquidTagOpenForMarkup =
159
+ variableSegment space* "in" space* liquidExpression<delimTag>
160
+ (space* "reversed")? argumentSeparatorOptionalComma
161
+ tagArguments (space* ",")? space*
162
+
163
+ // It's the same, the difference is support for different named arguments<delim>
164
+ liquidTagOpenTablerow = liquidTagOpenRule<"tablerow", liquidTagOpenForMarkup>
165
+
166
+ liquidTagOpenCase = liquidTagOpenRule<"case", liquidTagOpenCaseMarkup>
167
+ liquidTagOpenCaseMarkup = liquidExpression<delimTag> space*
168
+
169
+ liquidTagWhen = liquidTagRule<"when", liquidTagWhenMarkup>
170
+ liquidTagWhenMarkup = nonemptyListOf<liquidExpression<delimTag>, whenMarkupSep> space*
171
+ whenMarkupSep = space* ("," | "or" ~identifier) space*
172
+
173
+ liquidTagOpenIf = liquidTagOpenRule<"if", liquidTagOpenConditionalMarkup>
174
+ liquidTagOpenUnless = liquidTagOpenRule<"unless", liquidTagOpenConditionalMarkup>
175
+ liquidTagElsif = liquidTagRule<"elsif", liquidTagOpenConditionalMarkup>
176
+
177
+ liquidTagBreak = liquidTagRule<"break", empty>
178
+ liquidTagContinue = liquidTagRule<"continue", empty>
179
+ liquidTagElse = liquidTagRule<"else", empty>
180
+
181
+ liquidTagOpenConditionalMarkup = nonemptyListOf<condition<delimTag>, conditionSeparator> space*
182
+ conditionSeparator = &logicalOperator
183
+ condition<delim> = logicalOperator? space* (comparison<delim> | liquidExpression<delim>) space*
184
+ logicalOperator = ("and" | "or") ~identifier
185
+ comparison<delim> = liquidExpression<delim> space* comparator space* liquidExpression<delim>
186
+ comparator =
187
+ ( "=="
188
+ | "!="
189
+ | ">="
190
+ | "<="
191
+ | ">"
192
+ | "<")
193
+ | ("contains" ~identifier)
194
+
195
+ liquidTagOpenPaginate = liquidTagOpenRule<"paginate", liquidTagOpenPaginateMarkup>
196
+ liquidTagOpenPaginateMarkup =
197
+ liquidExpression<delimTag> space+ "by" space+ liquidExpression<delimTag> argumentSeparatorOptionalComma tagArguments (space* ",")? space*
198
+
199
+ liquidDrop = "{{" "-"? space* liquidDropCases "-"? "}}"
200
+ liquidDropCases = liquidVariable<delimVO> | liquidDropBaseCase
201
+ liquidDropBaseCase = anyExceptStar<delimVO>
202
+ liquidInlineComment = "{%" "-"? space* "#" space? tagMarkup "-"? "%}"
203
+
204
+ liquidRawTag =
205
+ | liquidRawTagImpl<"raw">
206
+ | liquidRawTagImpl<"javascript">
207
+ | liquidRawTagImpl<"schema">
208
+ | liquidRawTagImpl<"stylesheet">
209
+ | liquidRawTagImpl<"style">
210
+ liquidRawTagImpl<name> =
211
+ "{%" "-"? space* (name endOfIdentifier) space* tagMarkup "-"? "%}"
212
+ anyExceptStar<liquidRawTagClose<name>>
213
+ "{%" "-"? space* "end" (name endOfIdentifier) space* "-"? "%}"
214
+ liquidRawTagClose<name> =
215
+ "{%" "-"? space* "end" (name endOfIdentifier) space* "-"? "%}"
216
+
217
+ liquidBlockComment =
218
+ commentBlockStart
219
+ (liquidBlockComment | anyExceptPlus<commentBlockStart> | anyExceptPlus<commentBlockEnd>)*
220
+ commentBlockEnd
221
+ commentBlockStart = "{%" "-"? space* ("comment" endOfIdentifier) space* tagMarkup "-"? "%}"
222
+ commentBlockEnd = "{%" "-"? space* ("endcomment" endOfIdentifier) space* tagMarkup "-"? "%}"
223
+
224
+ liquidDoc =
225
+ liquidDocStart
226
+ liquidDocBody
227
+ liquidDocEnd
228
+
229
+ liquidDocStart = "{%" "-"? space* ("doc" endOfIdentifier) space* tagMarkup "-"? "%}"
230
+ liquidDocEnd = "{%" "-"? space* ("enddoc" endOfIdentifier) space* tagMarkup "-"? "%}"
231
+ liquidDocBody = anyExceptStar<liquidDocStart> | anyExceptStar<liquidDocEnd>
232
+
233
+ // In order for the grammar to "fallback" to the base case, this
234
+ // rule must pass if and only if we support what we parse. This
235
+ // implies that—since we don't support filters yet—we have a
236
+ // positive lookahead on "-}}" or "}}" in the rule. We do this
237
+ // because we'd otherwise positively match the following string
238
+ // instead of falling back to the other rule:
239
+ // {{ 'string' | some_filter }}
240
+ liquidVariable<delim> = liquidExpression<delim> liquidFilter<delim>* space* &delim
241
+
242
+ liquidExpression<delim> =
243
+ | liquidString<delim>
244
+ | liquidNumber
245
+ | liquidLiteral
246
+ | liquidRange<delim>
247
+ | liquidVariableLookup<delim>
248
+
249
+ liquidString<delim> = liquidSingleQuotedString<delim> | liquidDoubleQuotedString<delim>
250
+ liquidSingleQuotedString<delim> = "'" (anyExceptStar<"'"> | anyExceptStar<delim>) "'"
251
+ liquidDoubleQuotedString<delim> = "\"" (anyExceptStar<"\""> | anyExceptStar<delim>) "\""
252
+
253
+ liquidNumber = liquidFloat | liquidInteger
254
+ liquidInteger = "-"? digit+
255
+ liquidFloat = "-"? digit+ "." digit+
256
+
257
+ liquidLiteral =
258
+ ( "true"
259
+ | "false"
260
+ | "blank"
261
+ | "empty"
262
+ | "nil"
263
+ | "null"
264
+ ) endOfIdentifier
265
+
266
+ liquidRange<delim> =
267
+ "(" space* liquidExpression<delim> space* ".." space* liquidExpression<delim> space* ")"
268
+
269
+ liquidVariableLookup<delim> =
270
+ | variableSegment lookup<delim>*
271
+ | empty lookup<delim>+
272
+ lookup<delim> =
273
+ | indexLookup<delim>
274
+ | dotLookup
275
+ indexLookup<delim> = space* "[" space* liquidExpression<delim> space* "]"
276
+ dotLookup = space* "." space* identifier
277
+
278
+ liquidFilter<delim> = space* "|" space* identifier (space* ":" space* arguments<delim> (space* ",")?)?
279
+
280
+ arguments<delim> = nonemptyOrderedListOf<positionalArgument<delim>, namedArgument<delim>, argumentSeparator>
281
+ argumentSeparator = space* "," space*
282
+ argumentSeparatorOptionalComma = space* ","? space*
283
+ positionalArgument<delim> = liquidExpression<delim> ~(space* ":")
284
+ namedArgument<delim> = variableSegment space* ":" space* liquidExpression<delim>
285
+ tagArguments = listOf<namedArgument<delimTag>, argumentSeparatorOptionalComma>
286
+ filterArguments<delim> =
287
+ | complexArguments<delim>
288
+ | simpleArgument<delim>
289
+ complexArguments<delim> = arguments<delim> (space* "," space* simpleArgument<delim>)?
290
+ simpleArgument<delim> = liquidVariableLookup<delim>
291
+
292
+ variableSegment = (letter | "_") (~endOfTagName identifierCharacter)*
293
+ variableSegmentAsLookup = variableSegment
294
+ identifier = variableSegment "?"?
295
+
296
+ tagMarkup = anyExceptStar<delimTag>
297
+
298
+ liquidTagName =
299
+ letter (alnum | "_")*
300
+
301
+ blockName =
302
+ // Shopify blocks
303
+ ( "form"
304
+ | "paginate"
305
+ // Base blocks
306
+ | "capture"
307
+ | "case"
308
+ | "for"
309
+ | "ifchanged"
310
+ | "if"
311
+ | "unless"
312
+ | "tablerow"
313
+ ) endOfIdentifier
314
+
315
+ delimTag = "-%}" | "%}"
316
+ delimVO = "-}}" | "}}"
317
+ }
318
+
319
+ LiquidStatement <: Liquid {
320
+ Node := spaces listOf<LiquidStatement, statementSep> (space | newline)* spaces
321
+
322
+ // This is the big brains moment: we redefine space to exclude newlines.
323
+ //
324
+ // Which means that all our other Liquid rules can be reused
325
+ // without modification(!)
326
+ //
327
+ // We don't need to maintain rules like this:
328
+ // - liquidVariable<space>
329
+ // - liquidExpression<space>
330
+ // - variableLookup<space>
331
+ // - ... long list of stuff that takes space as param
332
+ // - liquidString<space>
333
+ //
334
+ // All we need is this little, VERY IMPORTANT, part right here that
335
+ // make it so we can parse the same way in Liquid tags.
336
+ //
337
+ // I'm putting in this huge comment so that it's more obvious.
338
+ space := " " | "\t"
339
+
340
+ LiquidStatement =
341
+ | spaces liquidBlockComment
342
+ | spaces liquidRawTag
343
+ | spaces liquidTagClose
344
+ | spaces liquidTagOpen
345
+ | spaces liquidTag
346
+ | spaces liquidInlineComment
347
+
348
+ liquidTagOpenRule<name, markup>
349
+ := (name ~identifierCharacter) space* markup &liquidStatementEnd
350
+
351
+ liquidTagRule<name, markup>
352
+ := (name ~identifierCharacter) space* markup &liquidStatementEnd
353
+
354
+ liquidTagClose
355
+ := "end" (blockName ~identifierCharacter) space* tagMarkup &liquidStatementEnd
356
+
357
+ liquidRawTagImpl<name>
358
+ := (name ~identifierCharacter) space* tagMarkup newline
359
+ anyExceptStar<liquidRawTagClose<name>>
360
+ "end" name space* &liquidStatementEnd
361
+
362
+ liquidRawTagClose<name>
363
+ := "end" name space* &liquidStatementEnd
364
+
365
+ liquidBlockComment :=
366
+ commentBlockStart statementSep
367
+ (listOf<liquidCommentBlockStatement, statementSep> statementSep)?
368
+ commentBlockEnd
369
+
370
+ liquidCommentBlockStatement =
371
+ | liquidBlockComment
372
+ | nonTerminalCommentLine
373
+
374
+ commentBlockStart
375
+ := ("comment" ~identifierCharacter) space* tagMarkup
376
+
377
+ commentBlockEnd
378
+ := ("endcomment" ~identifierCharacter) space* tagMarkup
379
+
380
+ nonTerminalCommentLine
381
+ = ~commentBlockEnd anyExceptPlus<newline>
382
+
383
+ liquidInlineComment
384
+ := "#" space? tagMarkup &liquidStatementEnd
385
+
386
+ tagMarkup := anyExceptStar<liquidStatementEnd>
387
+
388
+ // trailing whitespace, newline, + anything else before the next tag
389
+ statementSep = space* newline (space | newline)*
390
+
391
+ liquidStatementEnd = newline | end
392
+ delimTag := liquidStatementEnd
393
+ }
394
+
395
+ LiquidDoc <: Helpers {
396
+ Node := spaces ImplicitDescription (spaces (LiquidDocNode | TextNode))* spaces
397
+ LiquidDocNode =
398
+ | paramNode
399
+ | exampleNode
400
+ | descriptionNode
401
+ | fallbackNode
402
+
403
+ endOfDescription = strictSpace* openControl
404
+ descriptionContent = anyExceptStar<endOfDescription>
405
+ ImplicitDescription = descriptionContent
406
+
407
+ // By default, space matches new lines as well. We override it here to make writing rules easier.
408
+ strictSpace = " " | "\t"
409
+ // We use this as an escape hatch to stop matching TextNode and try again when one of these characters is encountered
410
+ openControl:= "@" | end
411
+
412
+ descriptionNode = "@description" space* descriptionContent
413
+
414
+ paramNode = "@param" strictSpace* paramType? strictSpace* (optionalParamName | paramName) (strictSpace* "-")? strictSpace* paramDescription
415
+ paramType = "{" strictSpace* paramTypeContent strictSpace* "}"
416
+ paramTypeContent = anyExceptStar<("}"| strictSpace)>
417
+
418
+ paramName = textValue
419
+ optionalParamName = "[" strictSpace* textValue strictSpace* "]"
420
+ textValue = identifierCharacter+
421
+
422
+ paramDescription = (~"]" anyExceptStar<endOfParam>)
423
+ endOfParam = strictSpace* (newline | end)
424
+
425
+ exampleNode = "@example" space* exampleContent
426
+ exampleContent = anyExceptStar<endOfExample>
427
+ endOfExample = strictSpace* ("@" | end)
428
+
429
+ fallbackNode = "@" anyExceptStar<endOfParam>
430
+ }
431
+
432
+ LiquidHTML <: Liquid {
433
+ Node := yamlFrontmatter? (spaces (HtmlNode | liquidNode | TextNode))*
434
+ openControl += "<"
435
+
436
+ yamlFrontmatter =
437
+ "---" newline anyExceptStar<"---"> "---" newline
438
+
439
+ HtmlNode =
440
+ | HtmlDoctype
441
+ | HtmlComment
442
+ | HtmlRawTag
443
+ | HtmlVoidElement
444
+ | HtmlSelfClosingElement
445
+ | HtmlTagClose
446
+ | HtmlTagOpen
447
+
448
+ // https://html.spec.whatwg.org/multipage/syntax.html#the-doctype
449
+ HtmlDoctype =
450
+ "<!" ("doctype"|"DOCTYPE") space+ ("html"|"HTML") spaces legacyDoctypeString? spaces ">"
451
+ legacyDoctypeString
452
+ = anyExceptPlus<">">
453
+
454
+ HtmlComment = "<!--" anyExceptStar<"-->"> "-->"
455
+
456
+ // These are black holes, we'll ignore what's in them
457
+ HtmlRawTag =
458
+ | HtmlRawTagImpl<"script">
459
+ | HtmlRawTagImpl<"style">
460
+ | HtmlRawTagImpl<"svg">
461
+
462
+ HtmlRawTagImpl<name> =
463
+ spaces TagStart<name>
464
+ (spaces (HtmlRawTagImpl<name> | AnyExceptPlus<TagStartorEnd<name>>))*
465
+ spaces TagEnd<name>
466
+ TagStart<name> = spaces "<" spaces name spaces AttrList spaces ">"
467
+ TagEnd<name> = spaces "</" spaces name spaces ">"
468
+ TagStartorEnd<name> = TagStart<name> | TagEnd<name>
469
+
470
+ HtmlVoidElement =
471
+ spaces "<" voidElementName &(space | "/" | ">") spaces AttrList spaces "/"? spaces ">"
472
+
473
+ HtmlSelfClosingElement =
474
+ spaces "<" tagName spaces AttrList spaces "/>"
475
+
476
+ HtmlTagOpen =
477
+ spaces "<" tagName spaces AttrList spaces ">"
478
+
479
+ HtmlTagClose =
480
+ spaces "</" tagName spaces ">"
481
+
482
+ tagName = leadingTagNamePart trailingTagNamePart*
483
+
484
+ // The difference here is that the first text part must start
485
+ // with a letter, but trailing text parts don't have that
486
+ // requirement
487
+ leadingTagNamePart =
488
+ | liquidDrop
489
+ | leadingTagNameTextNode
490
+
491
+ trailingTagNamePart =
492
+ | liquidDrop
493
+ | trailingTagNameTextNode
494
+
495
+ leadingTagNameTextNode = letter (alnum | "-" | ":")*
496
+ trailingTagNameTextNode = (alnum | "-" | ":")+
497
+
498
+ AttrList = (spaces Attr)*
499
+
500
+ Attr =
501
+ spaces (AttrSingleQuoted | AttrDoubleQuoted | AttrUnquoted | liquidNode | attrEmpty)
502
+
503
+ attrEmpty = attrName
504
+
505
+ AttrUnquoted = spaces attrName spaces "=" spaces attrUnquotedValue
506
+ AttrSingleQuoted = spaces attrName spaces "=" spaces singleQuote attrSingleQuotedValue singleQuote
507
+ AttrDoubleQuoted = spaces attrName spaces "=" spaces doubleQuote attrDoubleQuotedValue doubleQuote
508
+
509
+ attrName = (liquidDrop | attrNameTextNode)+
510
+
511
+ // https://html.spec.whatwg.org/#attributes-2
512
+ fake1 = space | quotes | "=" | ">" | "/>" | "{{" | "{%" | controls | noncharacters
513
+ attrNameTextNode = anyExceptPlus<fake1>
514
+ attrUnquotedValue = (liquidDrop | attrUnquotedTextNode)*
515
+ attrSingleQuotedValue = (liquidNode | attrSingleQuotedTextNode)*
516
+ attrDoubleQuotedValue = (liquidNode | attrDoubleQuotedTextNode)*
517
+
518
+ fake2 = space | quotes | "=" | "<" | ">" | "`" | "{{" | "{%"
519
+ attrUnquotedTextNode = anyExceptPlus<fake2>
520
+ fake3 = singleQuote | "{{" | "{%"
521
+ fake4 = doubleQuote | "{{" | "{%"
522
+ attrSingleQuotedTextNode = anyExceptPlus<fake3>
523
+ attrDoubleQuotedTextNode = anyExceptPlus<fake4>
524
+
525
+ quotes = singleQuote | doubleQuote
526
+
527
+ // https://www.w3.org/TR/2011/WD-html-markup-20110113/syntax.html#void-element
528
+ voidElementName =
529
+ ( "area"
530
+ | "base"
531
+ | "br"
532
+ | "col"
533
+ | "command"
534
+ | "embed"
535
+ | "hr"
536
+ | "img"
537
+ | "input"
538
+ | "keygen"
539
+ | "link"
540
+ | "meta"
541
+ | "param"
542
+ | "source"
543
+ | "track"
544
+ | "wbr"
545
+ ) ~identifierCharacter
546
+ }
547
+
548
+ StrictLiquid <: Liquid {
549
+ liquidTag := liquidTagStrict
550
+ liquidTagOpen := liquidTagOpenStrict
551
+ }
552
+
553
+ StrictLiquidStatement <: LiquidStatement {
554
+ liquidTag := liquidTagStrict
555
+ liquidTagOpen := liquidTagOpenStrict
556
+ }
557
+
558
+ StrictLiquidHTML <: LiquidHTML {
559
+ liquidTag := liquidTagStrict
560
+ liquidTagOpen := liquidTagOpenStrict
561
+ }
562
+
563
+ WithPlaceholderLiquid <: Liquid {
564
+ liquidFilter<delim> := space* "|" space* identifier (space* ":" space* filterArguments<delim> (space* ",")?)?
565
+ liquidTagContentForMarkup :=
566
+ contentForType (argumentSeparatorOptionalComma completionModeContentForTagArgument) (space* ",")? space*
567
+ liquidTagRenderMarkup :=
568
+ snippetExpression renderVariableExpression? renderAliasExpression? completionModeRenderArguments
569
+ liquidTagName := (letter | "█") (alnum | "_")*
570
+ variableSegment := (letter | "_" | "█") (identifierCharacter | "█")*
571
+ liquidDoc :=
572
+ liquidDocStart
573
+ liquidDocBody
574
+ liquidDocEnd?
575
+ }
576
+
577
+ WithPlaceholderLiquidStatement <: LiquidStatement {
578
+ liquidFilter<delim> := space* "|" space* identifier (space* ":" space* filterArguments<delim> (space* ",")?)?
579
+ liquidTagContentForMarkup :=
580
+ contentForType (argumentSeparatorOptionalComma completionModeContentForTagArgument) (space* ",")? space*
581
+ liquidTagRenderMarkup :=
582
+ snippetExpression renderVariableExpression? renderAliasExpression? completionModeRenderArguments
583
+ liquidTagName := (letter | "█") (alnum | "_")*
584
+ variableSegment := (letter | "_" | "█") (identifierCharacter | "█")*
585
+ liquidDoc :=
586
+ liquidDocStart
587
+ liquidDocBody
588
+ liquidDocEnd?
589
+ }
590
+
591
+ WithPlaceholderLiquidHTML <: LiquidHTML {
592
+ liquidFilter<delim> := space* "|" space* identifier (space* ":" space* filterArguments<delim> (space* ",")?)?
593
+ liquidTagContentForMarkup :=
594
+ contentForType (argumentSeparatorOptionalComma completionModeContentForTagArgument) (space* ",")? space*
595
+ liquidTagRenderMarkup :=
596
+ snippetExpression renderVariableExpression? renderAliasExpression? completionModeRenderArguments
597
+ liquidTagName := (letter | "█") (alnum | "_")*
598
+ variableSegment := (letter | "_" | "█") (identifierCharacter | "█")*
599
+ leadingTagNameTextNode := (letter | "█") (alnum | "-" | ":" | "█")*
600
+ trailingTagNameTextNode := (alnum | "-" | ":" | "█")+
601
+ liquidDoc :=
602
+ liquidDocStart
603
+ liquidDocBody
604
+ liquidDocEnd?
605
+ }
@@ -0,0 +1,67 @@
1
+ # Ohm-WASM Go Integration
2
+
3
+ This directory contains a Go implementation for running Ohm grammars compiled to WebAssembly. It provides a simple API to load grammar modules, match input against them, and access the resulting concrete syntax trees.
4
+
5
+ ## Overview
6
+
7
+ The implementation consists of two main components:
8
+
9
+ 1. **matcher.go**: A Go implementation of the JavaScript `WasmMatcher` class from the Ohm `wasm` package
10
+ 2. **testmain.go**: A command-line program that demonstrates how to use the WasmMatcher
11
+
12
+ ## WasmMatcher
13
+
14
+ The `WasmMatcher` class provides a high-level API for working with Ohm grammars compiled to WebAssembly:
15
+
16
+ ```go
17
+ // Create a new matcher
18
+ matcher := NewWasmMatcher(ctx)
19
+
20
+ // Load a grammar module
21
+ err := matcher.LoadModule("path/to/grammar.wasm")
22
+
23
+ // Set input text
24
+ matcher.SetInput("text to match")
25
+
26
+ // Match against the grammar
27
+ success, err := matcher.Match()
28
+
29
+ // Match against a specific rule
30
+ success, err := matcher.MatchRule("specificRule")
31
+
32
+ // Access the concrete syntax tree
33
+ cstRoot, err := matcher.GetCstRoot()
34
+ ```
35
+
36
+ ## Command-Line Usage
37
+
38
+ You can use the command-line program to test Ohm grammars:
39
+
40
+ ```
41
+ # Test the simple add function (automatically detected)
42
+ ./testmain -wasm ../data/_add.wasm
43
+
44
+ # Match input against a grammar
45
+ ./testmain -wasm path/to/grammar.wasm -input "text to match"
46
+
47
+ # Specify a start rule
48
+ ./testmain -wasm path/to/grammar.wasm -input "text to match" -rule "StartRule"
49
+ ```
50
+
51
+ ### Example with ES5 Grammar
52
+
53
+ ```
54
+ ./testmain -wasm ../data/_es5.wasm -input "var x = 3;"
55
+ ```
56
+
57
+ ## Build Instructions
58
+
59
+ Use the Makefile in the parent directory to build and test:
60
+
61
+ ```
62
+ # Build the testmain program
63
+ make test/go/testmain
64
+
65
+ # Run the test with the ES5 grammar
66
+ make go-test-es5
67
+ ```