<div dir="ltr">Hi,<br><br>I'm working on a lens that has two errors:<br><br> >>  1 (*<br> >>  2 # example configuration follows:<br> >>  3 # default = value<br> >>  4 key = value<br> >>  5<br> >>  6 # default = value # inline comment<br> >>  7 key = value # inline comment<br> >>  8 *)<br> >>  9<br> >> 10 (*<br> >> 11 # key/value formats:<br> >> 12<br> >> 13 keys<br> >> 14     [a-z_]<br> >> 15<br> >> 16 values<br> >> 17     boolean:            true/false<br> >> 18     int                 0, 100<br> >> 19     real                3.0<br> >> 20     hex int             ffeedd<br> >> 21     string              "..."<br> >> 22     unquoted string     sdl, f, f2<br> >> 23 *)<br> >> 24<br> >> 25 (*<br> >> 26 # quoted string regex scratchpad<br> >> 27 quoted string regex =<br> >> 28     good:<br> >> 29         "asdf\"qwer"<br> >> 30         "asdf\\qwer"<br> >> 31         "asdf\\\\\"qwer"<br> >> 32     bad:<br> >> 33         "asdf\\"qwer"<br> >> 34         "asdf\\\\\\"qwer"<br> >> 35<br> >> 36     /.*/ - /.*(\\)*[^\]".*/<br> >> 37<br> >> 38     /([^"](\")?)*/<br> >> 39 *)<br> >> 40<br> >> 41 module ConfigObj =<br> >> 42     let _               = print_regexp /"/<br> >> 43     let _               = print_string "\n"<br> >> 44     let var0            = "\""<br> >> 45     let _               = print_string (var0 . "\n")<br> >> 46     let _               = print_string "\n"<br> >> 47<br> >> 48     let var1            = "\"asdf\\\\\\\\"qwer\""<br> >> 49     let _               = print_string (var1 . "\n")<br> >> 50     let _               = print_string ((regexp_match (/\".*\"/ - /\"(.*[^\])?([\]{2})*".*\"/) var1) . "\n")<br> >> 51<br> >> 52     let option          = key /[a-z]([a-z_]*[a-z])?/<br> >> 53     let value_bool      = store /(true|false)/ . [ label "type" . value "bool" ]<br> >> 54     let value_int       = store /(0|[1-9][0-9]*)/ . [ label "type" . value "int" ]<br> >> 55     let value_decimal   = store ((lens_ctype value_int) . /\.[0-9]+/) . [ label "type" . value "decimal" ]<br> >> 56     let value_string    = (del "\"" "\"") . (store (/.*/ - /(.*[^\]|)([\]{2})*".*/)) . (del "\"" "\"") . [ label "type" . value "string" ]<br> >> 57     let value_all       = value_bool | value_int | value_decimal<br> >> 58     let sep_assign      = del /[ \t]*=[ \t]*/ " = "<br> >> 59     let sep_comment     = del /[ \t]*#[ \t]*/ " # "<br> >> 60     let record_comment  = [ label "comment" . sep_comment . store /([^ \t\n].*)?/ ]<br> >> 61     let record          = option . sep_assign . value_all . record_comment?<br> >> 62     let record_not      = label "comment" . store (/([^ \t\n].*)?/ - lens_ctype record)<br> >> 63     let comment         = del /#[ \t]*/ "# " . ( [ record . [ label "commented" ] ] | [ record_not ] )<br> >> 64     let line            = del /[ \t]*/ "" . ( comment | [ record ] ) . del "\n" "\n"<br> >> 65     let lns             = line *<br><br>The first is a regex problem: I want to match double-quoted c-style strings, ie strings with escape sequences such as "\"", "\\\"" and so on. The regex I've crafted (line#50) evidently fits the bill - try modifying the input test values (line#48) to verify - so I don't understand why the derived lens (line#56) is failing, and thereby causing this "ambiguous concatenation" error:<br><br> >> Syntax error in lens definition<br> >> configobj.aug:61.4-.75:Failed to compile record<br> >> configobj.aug:61.26-.75:exception: ambiguous concatenation<br> >>       First regexp: /([a-z]([a-z_]*[a-z])?)([ \t]*=[ \t]*)((((true|false)))|(((0|[1-9][0-9]*)))|(((((0|[1-9][0-9]*)))(\\.[0-9]+)))|((")(([^\n"\\][^\n"\\]*\\\\|\\\\)([^\n\\][^\n"\\]*\\\\)*\\\\(([^\n"\\][^\n"\\]*\\\\|\\\\)([^\n\\][^\n"\\]*\\\\)*\\\\)*(([^\n"\\][^\n"\\]*\\\\|\\\\)([^\n\\][^\n"\\]*\\\\)*([^\n\\][^\n"\\]*|)|[^\n"\\][^\n"\\]*|)|([^\n"\\][^\n"\\]*\\\\|\\\\)([^\n\\][^\n"\\]*\\\\)*([^\n\\][^\n"\\]*|)|[^\n"\\][^\n"\\]*|)(")))/<br> >>       Second regexp: /(([ \t]*#[ \t]*)(([^ \t\n].*)?))?/<br> >>       'a="\\"#"' can be split into<br> >>       'a="\\"|=|#"'<br> >><br> >>      and<br> >>       'a="\\"#"|=|'  <----- not possible per the regex<br> >><br> >>     First lens: configobj.aug:61.26-.57:<br> >>     Second lens: configobj.aug:61.60-.75:<br><br>The second problem - you'll see if the first is fixed - is a limitation of augeas' tree-text conversion, the inability to differentiate trees on depth. This generates the error "exception: overlapping lenses in tree union.put" and crops up in two locations:<br><br> '[ record . [ label "commented" ] ]' (line#63) ----vs---- '[ record_not ]' (line#63)<br>    ::: The "record_not" label of "comment" is also a possible valid label of the "record" lens [line#52]. Hacky workaround is to change the label to an invalid key, ie "comment2", etc.<br> '[ record . [ label "commented" ] ]' (line#63) ----vs---- '[ record ]' (line#64)<br>    ::: Unlike previous, no hacky workaround.<br><br>Obviously this can be fixed by scanning the *depth* of the tree. In both cases, one branch is guaranteed to have a subnode with the label "commented" unlike the other. While augeas doesn't implement this, there was a suggestion on the mailing list regarding a lens-based workaround[1] that I didn't understand. I'd appreciate if someone could provide a concrete example for my case.<br><br><br>Sincerely,<br><br><br>[1] <a href="https://www.redhat.com/archives/augeas-devel/2009-June/msg00088.html">https://www.redhat.com/archives/augeas-devel/2009-June/msg00088.html</a><br></div>