<div dir="ltr"><br><br><div class="gmail_quote">On Wed, Aug 20, 2008 at 2:36 PM, Free Ekanayaka <span dir="ltr"><<a href="mailto:free@64studio.com">free@64studio.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
 RP> Nicolas Valcarcel (aka nxvl) was already working on this lens, so I'm sure<br>
  RP> he will be interested in it.<br>
<br>
Oh, I didn't now it. Is his work already committed somewhere? I would<br>
be glad to collaborate.</blockquote><div><br><br>I think he has a bzr branch on Launchpad with his work. Haven't seen a single line myself so far though.<br><br> </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div class="Ih2E3d">
  >>(* Define a generic entry *)<br>
  >>>let entry (l:string) = [ spc . label l . value_to_spc ]<br>
  >>><br>
  >>>(* Define a stanza type *)<br>
  >>>let type (t:string) = del t t . entry t<br>
  >>><br>
  >><br>
<br>
</div><br>  RP> It seems to me that all this is equivalent to<br>
<br>
  RP> let entry (l:string) = [ key l . spc . value_to_spc ]<br>
<br>
<br>
  RP> Maybe you should use Util.indent instead of Util.del_opt_ws (aka spc for<br>
  RP> you) here, since Util.del_opt_ws will insert a space before new entries by<br>
  RP> default.<br>
<br>
If I simply replace Util.del_opt_ws with Util.indent, I get a series<br>
of errors like this one:<br>
<br>
lenses/interfaces.aug:26.3-.80:Failed to compile option<br>
lenses/interfaces.aug:26.18-.72:exception: ambiguous concatenation<br>
      'ifacA' can be split into<br>
      'ifa|=|cA'<br>
<br>
     and<br>
      'ifac|=|A'<br>
<br>
    First lens: lenses/interfaces.aug:26.18-.57<br>
    Second lens: lenses/interfaces.aug:9.22-.59<br>
<br>
Should I change something else too?<br>
<div class="Ih2E3d"></div></blockquote><div><br><br>Sorry, my mistake. Util.del_ws_spc is for the spaces only, while you can put Util.indent in the beginning of each entry. del_ws_spc deletes /[ \t]+/ while indent deletes /[ \t]*/.<br>
<br>In any case, you will probably end up using the \ trick instead for spc, and indent in front of each entry.<br><br> </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div class="Ih2E3d"> >>(* Define a iface stanza *)<br>
  >>>let option = [ spc . key /([a-z]|-)+/ . spc . value_to_eol . eol ]<br>
  >>>let iface = type "iface" . entry "family" . entry "method" . eol .<br>
  >>>option*<br>
  >>><br>
  >><br>
<br>
</div>  RP> And there I see why you "have to" indent options. The best way around would<br>
  RP> probably be to specify the list of known options, or at least specify that<br>
  RP> options cannot be "iface", "family" or "method".<br>
<br>
I think the latter is better, because there are many options and even<br>
more can be added by packages like wireless-tools.<br>
</blockquote><div><br>I agree with this. This is the way I took with php.aug aswell. One example of the first case is dput.aug, since it has only few options.<br><br> <br></div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div class="Ih2E3d">
  >>(* Note that allow-auto and auto are synonims *)<br>
  >>>let allow_auto = type "allow-auto". (entry "allow-auto")* . eol<br>
  >>><br>
  >><br>
</div>  RP> You could also have<br>
<br>
  RP> let type (r:regexp) (t:string) = del r t . entry<br>
<br>
  RP> And then<br>
<br>
  RP> let auto = type /(allow_)?auto/ "auto" (entry "auto")* . eol<br>
<br>
  RP> If these are stricly equivalent. This way, allow_auto and auto will be<br>
  RP> parsed equally, but the type will default to "auto".<br>
<br>
Yes, I had thought it too, but didn't find a way to do it. I tried<br>
your hint, but I'm getting an error like:<br>
<br>
lenses/interfaces.aug:21.46-.51:type error: expected string, regexp, lens, or filter but found string -> lens</blockquote><div><br><br>I guess my definition of type is wrong. It should read <br><br><div style="margin-left: 40px;">
let type (r:regexp) (t:string) = del r t . entry t<br></div><br>since entry takes a string argument.<br><br> </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
 RP> You don't have to number nodes like this. It actually makes it a bit<br>
  RP> confusing to parse<br>
<br>
  RP>         { "1"<br>
  RP>             { "auto" = "lo" }<br>
  RP>             { "auto" = "eth0" } }<br>
  RP>         { "2"<br>
  RP>             { "allow-hotplug" = "eth1" }}<br>
  RP>         {}<br>
  RP>         { "3"<br>
  RP>             { "iface" = "lo" }<br>
  RP>             { "family" = "inet"}<br>
  RP>             { "method" = "loopback"} }<br>
<br>
<br>
  RP> if more complicated than<br>
<br>
  RP>         { "auto" = "lo" }<br>
  RP>         { "auto" = "eth0" }<br>
  RP>         { "allow-hotplug" = "eth1" }<br>
  RP>         {}<br>
  RP>         {"iface"<br>
  RP>             { "name" = "lo" }<br>
  RP>             { "family" = "inet"}<br>
  RP>             { "method" = "loopback"} }<br>
<br>
<br>
  RP> which is much easier to parse with xpath. This means that iface could be<br>
  RP> rewritten as<br>
<br>
  RP> let iface = label "iface" . entry "name" . entry "family" . entry "method" .<br>
  RP> eol . option*<br>
<br>
  RP> and the same with other sections.<br>
<br>
Initially I planned to do it like you suggest (without seq), and it<br>
was easy to do for records like iface. However I'm having difficulties<br>
with the auto construct, which can accept more than one interface,<br>
like:<br>
<br>
auto lo eth0<br>
<br>
which I can't really turn to:<br>
<br>
  { "auto" = "lo" }<br>
  { "auto" = "eth0" } }<br>
<br>
I've tried with:<br>
<div class="Ih2E3d"><br>
   let entry (l:string) = [ spc . label l . value_to_spc ]<br>
</div>   let auto  = del "auto" "auto" . (entry "auto")+ . eol<br>
<br>
but I get:<br>
<br>
lenses/interfaces.aug:31.13-.42:exception: ambiguous tree iteration<br>
      'auto/auto/' can be split into<br>
      'auto/|=|auto/'<br>
<br>
     and<br>
      'auto/auto/|=|'<br>
<br>
Note that using concatenation instead of repetition does work:<br>
<br>
   let auto  = del "auto" "auto" . entry "auto" . entry "auto" . eol<br>
<br>
but of course it hard-wires the number of parameters. I'm a bit<br>
confused here.<br>
<div class="Ih2E3d"></div></blockquote><div><br><br>sshd.aug has a similar issue with "AcceptEnv" entries. David got around this by using seq inside the entry instead of outside.<br><br><div style="margin-left: 40px;">
let array_entry (k:string) =<br>     let value = store /[^ \t\n]+/ in<br>     [ key k . [ sep . seq k . value]* . eol ]<br>let accept_env = array_entry "AcceptEnv"<br></div><br>which maps AcceptEnv like this<br>
<br><div style="margin-left: 40px;">  let accept_env = "Protocol 2\nAcceptEnv LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT \nAcceptEnv LC_IDENTIFICATION LC_ALL\n"<br><br>  test Sshd.lns get accept_env =<br>
    { "Protocol" = "2" }<br>    { "AcceptEnv"<br>        { "1" = "LC_PAPER" }<br>        { "2" = "LC_NAME" }<br>        { "3" = "LC_ADDRESS" }<br>
        { "4" = "LC_TELEPHONE" }<br>        { "5" = "LC_MEASUREMENT" } }<br>     { "AcceptEnv"<br>        { "6" = "LC_IDENTIFICATION" }<br>        { "7" = "LC_ALL" } }<br>
</div><br><br>This way, it doesn't affect the rest of the file, but still fixes the mapping issue that you're facing.<br><br> </div><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<div class="Ih2E3d"> >>(* Define lens *)<br>
  >>>let lns = ( comment | stanza )*<br>
  >><br>
  >><br>
<br>
</div>  RP> Have you tried putting comments in the middle of stanzas ?<br>
  RP> It seems to me that the option field could be a comment aswell.<br>
<br>
I did not try, it problably needs to be fixed.<br>
</blockquote><div><br><br>I faced this issue in inifile.aug and bbhosts.aug (and more). You could get around it with something like<br><br><br><div style="margin-left: 40px;">let iface      = type "iface" . entry "family" . entry "method" . eol <br>
                     . (option|comment|empty)*<br>let mapping = type "mapping" . eol<br>                     . (option|comment|empty)*<br><br></div><div style="margin-left: 40px;">let stanza = iface <br>                | auto <br>
                | allow_auto <br>                | allow_hotplug <br>                | mapping<br></div><div style="margin-left: 40px;">let lns = (comment|empty)* . stanza*<br><br></div><br></div><div>Oh yes, forgot to tell you that you need Util.empty when yo use Util.comment, since once comments are mapped, you still need to remove empty lines.<br>
<br><br><br>Ciao<br><br><br>Raphaël<br><br></div></div><br></div>