Skip to content

Instantly share code, notes, and snippets.

@jg-rp
Last active September 9, 2023 21:34
Show Gist options
  • Save jg-rp/e2dc4da9e5033e087e46016008a9d91c to your computer and use it in GitHub Desktop.
Save jg-rp/e2dc4da9e5033e087e46016008a9d91c to your computer and use it in GitHub Desktop.
Liquid template expression syntax
expression : ID "=" filtered
filtered : left { "|" filter }
left : literal
| path
| range
literal : FLOAT
| INTEGER
| STRING
| TRUE
| FALSE
| NIL
| NULL
| EMPTY
| BLANK
path : ID { prop }
prop : bracketed
| dotted
bracketed : "[" elem "]"
dotted : "." ID
elem : path
| INTEGER
| STRING
range : "(" rangearg DOUBLEDOT rangearg ")"
rangearg : INTEGER
| FLOAT
| path
filter : ID [ ":" args ]
args : arg { "," arg }
arg : parg
| kwarg
parg : literal
| path
kwarg : ID ":" parg
expr : object [ comp ] { logic_op expr }
comp : comp_op object
logic_op : "and"
| "or"
comp_op : "=="
| "<"
| ">"
| "<="
| ">="
| "!="
| "<>"
| "contains"
object : literal
| path
| range
literal : FLOAT
| INTEGER
| STRING
| TRUE
| FALSE
| NIL
| NULL
| EMPTY
| BLANK
path : ID { prop }
prop : bracketed
| dotted
bracketed : "[" elem "]"
dotted : "." ID
elem : path
| INTEGER
| STRING
range : "(" range_arg DOUBLEDOT range_arg ")"
range_arg : INTEGER
| FLOAT
| path
expr : left { "|" filter }
left : literal
| path
| range
literal : FLOAT
| INTEGER
| STRING
| TRUE
| FALSE
| NIL
| NULL
| EMPTY
| BLANK
path : ID { prop }
prop : bracketed
| dotted
bracketed : "[" elem "]"
dotted : "." ID
elem : path
| INTEGER
| STRING
range : "(" rangearg DOUBLEDOT rangearg ")"
rangearg : INTEGER
| FLOAT
| path
filter : ID [ ":" args ]
args : arg { "," arg }
arg : parg
| kwarg
parg : literal
| path
kwarg : ID ":" parg
expression : filtered [ condition ]
filtered : object { "|" filter }
condition : "if" boolean [ alternative ] [ tailfilters ]
boolean : object [ comparison ] { logic_op boolean }
alternative : "else" filtered
tailfilters : "||" filter { "|" filter }
comparison : comp_op object
logic_op : "and"
| "or"
comp_op : "=="
| "<"
| ">"
| "<="
| ">="
| "!="
| "<>"
| "contains"
object : literal
| path
| range
literal : FLOAT
| INTEGER
| STRING
| TRUE
| FALSE
| NIL
| NULL
| EMPTY
| BLANK
path : ID { prop }
prop : bracketed
| dotted
bracketed : "[" elem "]"
dotted : "." ID
elem : path
| INTEGER
| STRING
range : "(" rangearg DOUBLEDOT rangearg ")"
rangearg : INTEGER
| FLOAT
| path
filter : ID [ ":" args ]
args : arg { "," arg }
arg : parg
| kwarg
parg : literal
| path
kwarg : ID ":" parg
expr : ID "in" iterable { option }
iterable : path
| range
option : limit
| offset
| "reversed"
limit : "limit" ":" limitarg
offset : "offset" ":" offsetarg
limitarg : INTEGER
| path
offsetarg : INTEGER
| path
| "continue"
path : ID { prop }
prop : bracketed
| dotted
bracketed : "[" elem "]"
dotted : "." ID
elem : path
| INTEGER
| STRING
range : "(" rangearg DOUBLEDOT rangearg ")"
rangearg : INTEGER
| FLOAT
| path
@jg-rp
Copy link
Author

jg-rp commented Nov 15, 2022

The BNF-like syntax used here is that favoured by the SLY project, which is no longer under active development.

Note that the inline if expression described here is a non-standard extension to the filtered expression.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment