(* Module: Toml Parses TOML files Author: Raphael Pinson About: Reference https://toml.io/en/v1.0.0 About: License This file is licensed under the LGPL v2+, like the rest of Augeas. About: Lens Usage To be documented About: Configuration files This lens applies to TOML files. About: Examples The file contains various examples and tests. *) module Toml = (* Group: base definitions *) (* View: comment A simple comment *) let comment = IniFile.comment "#" "#" (* View: empty An empty line *) let empty = Util.empty_dos (* View: eol An end of line *) let eol = Util.doseol (* Group: value entries *) let bare_re_noquot = (/[^][", \t\r\n]/ - "#") let bare_re = (/[^][,\r=]/ - "#")+ let no_quot = /[^]["\r\n]*/ let bare = Quote.do_dquote_opt_nil (store (bare_re_noquot . (bare_re* . bare_re_noquot)?)) let quoted = Quote.do_dquote (store (/[^"]/ . "#"* . /[^"]/)) let ws = del /[ \t\n]*/ "" let space_or_empty = [ del /[ \t\n]+/ " " ] let comma = Util.del_str "," . (space_or_empty | comment)? let lbrace = Util.del_str "{" . (space_or_empty | comment)? let rbrace = Util.del_str "}" let lbrack = Util.del_str "[" . (space_or_empty | comment)? let rbrack = Util.del_str "]" (* This follows the definition of 'string' at https://www.json.org/ It's a little wider than what's allowed there as it would accept nonsensical \u escapes *) let triple_dquote = Util.del_str "\"\"\"" let str_store = Quote.dquote . store /([^\\"]|\\\\["\/bfnrtu\\])*/ . Quote.dquote let str_store_multi = triple_dquote . eol . store /([^\\"]|\\\\["\/bfnrtu\\])*/ . del /\n[ \t]*/ "\n" . triple_dquote let str_store_literal = Quote.squote . store /([^\\']|\\\\['\/bfnrtu\\])*/ . Quote.squote let integer = let base10 = /[+-]?[0-9_]+/ in let hex = /0x[A-Za-z0-9]+/ in let oct = /0o[0-7]+/ in let bin = /0b[01]+/ in [ label "integer" . store (base10 | hex | oct | bin) ] let float = let n = /[0-9_]+/ in let pm = /[+-]?/ in let z = pm . n in let decim = "." . n in let exp = /[Ee]/ . z in let num = z . decim | z . exp | z . decim . exp in let inf = pm . "inf" in let nan = pm . "nan" in [ label "float" . store (num | inf | nan) ] let str = [ label "string" . str_store ] let str_multi = [ label "string_multi" . str_store_multi ] let str_literal = [ label "string_literal" . str_store_literal ] let bool (r:regexp) = [ label "bool" . store r ] let date_re = /[0-9]{4}-[0-9]{2}-[0-9]{2}/ let time_re = /[0-9]{1,2}:[0-9]{2}:[0-9]{2}(\.[0-9]+)?[A-Z]*/ let datetime = [ label "datetime" . store (date_re . /[T ]/ . time_re) ] let date = [ label "date" . store date_re ] let time = [ label "time" . store time_re ] let norec = str | str_multi | str_literal | integer | float | bool /true|false/ | datetime | date | time let array (value:lens) = [ label "array" . lbrack . ( ( Build.opt_list value comma . (del /,?/ "") . (space_or_empty | comment)? . rbrack ) | rbrack ) ] let array_norec = array norec (* This is actually no real recursive array, instead it is one or two dimensional For more info on this see https://github.com/hercules-team/augeas/issues/715 *) let array_rec = array (norec | array_norec) let entry_base (value:lens) = [ label "entry" . store Rx.word . Sep.space_equal . value ] let inline_table (value:lens) = [ label "inline_table" . lbrace . ( (Build.opt_list (entry_base value) comma . space_or_empty? . rbrace) | rbrace ) ] let entry = [ label "entry" . Util.indent . store Rx.word . Sep.space_equal . (norec | array_rec | inline_table (norec|array_norec)) . (eol | comment) ] (* Group: tables *) (* View: table_gen A generic table *) let table_gen (name:string) (lbrack:string) (rbrack:string) = let title = Util.indent . label name . Util.del_str lbrack . store /[^]\r\n.]+(\.[^]\r\n.]+)*/ . Util.del_str rbrack . eol in [ title . (entry|empty|comment)* ] (* View: table A table or array of tables *) let table = table_gen "table" "[" "]" | table_gen "@table" "[[" "]]" (* Group: lens *) (* View: lns The Toml lens *) let lns = (entry | empty | comment)* . table*