Skip to content

Instantly share code, notes, and snippets.

@vbarda
Last active December 6, 2020 13:48
Show Gist options
  • Save vbarda/2c716d1025446ee6511e9effd0bb2e41 to your computer and use it in GitHub Desktop.
Save vbarda/2c716d1025446ee6511e9effd0bb2e41 to your computer and use it in GitHub Desktop.
F5 Config Parser
import lark
import re
f5_config_grammar = r"""
// define rules
?start: array
?value: object
| value_set
| string
| ESCAPED_STRING -> quoted_string
array : [command_block ("\n" command_block)*]
// Command block = command + method + arguments (command token + key-value pair)
command_block: command " " pair
object : "{\n" [pair ("\n" pair)*] "\n}"
value_set : "{ " [(value " ")*] "}"
pair : string " " value
command: COMMAND_TOKEN
string : STRING_TOKEN
// define tokens (NOTE: longer tokens should be defined first, i.e. "auth token" before "auth")
COMMAND_TOKEN: "auth token" | "auth" | "sys"
STRING_TOKEN : /([a-zA-Z0-9\-_.=$\/\:])+/
%import common.ESCAPED_STRING
"""
class F5ConfigTransformer(lark.Transformer):
def pair(self, values):
assert len(values) == 2
k, v = values
return {k: v}
def object(self, values):
merged = {}
for value in values:
merged = {**merged, **value}
return merged
@lark.v_args(inline=True)
def quoted_string(self, value):
return value[1:-1]
array = list
command_block = pair
command = lark.v_args(inline=True)(str)
string = lark.v_args(inline=True)(str)
parser = lark.Lark(f5_config_grammar, parser="lalr", transformer=F5ConfigTransformer())
# TODO: figure out how to ignore tabs directly in parser
# clean_config_text = config_text.replace(" ", "")
# parser.parse(clean_config_text)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment