drowzy / hxl

An Elixir implementation of HCL.
Apache License 2.0
30 stars 1 forks source link

Incorrect parsing of repeated blocks #8

Closed jclem closed 1 year ago

jclem commented 1 year ago

Given the following HCL:

foo {
  bar = 1
}

foo {
  bar = 2
}

HXL decodes it like so:

%{"foo" => %{"bar" => 2}}

While the AST decoding is correct, the decoding-to-Elixir is not an accurate representation of the document. Instead, it should be:

%{"foo" => [%{"bar" => 1}, %{"bar" => 2}]}

In other words, HXL.decode/2 is lossy, currently. Note that HXL.decode_ast_ast/1 is fine:

 %HXL.Ast.Body{
   statements: [
     %HXL.Ast.Block{
       type: "foo",
       labels: [],
       body: %HXL.Ast.Body{
         statements: [
           %HXL.Ast.Attr{name: "bar", expr: %HXL.Ast.Literal{value: {:int, 1}}}
         ]
       }
     },
     %HXL.Ast.Block{
       type: "foo",
       labels: [],
       body: %HXL.Ast.Body{
         statements: [
           %HXL.Ast.Attr{name: "bar", expr: %HXL.Ast.Literal{value: {:int, 2}}}
         ]
       }
     }
   ]
 }
drowzy commented 1 year ago

Thanks for the issue! I pushed a potential fix:

foo {
  bar = 1
}

foo {
  bar = 2
}
%{"foo" => [%{"bar" => 1}, %{"bar" => 2}]}
foo {
  bar {
    baz = 1
  }
}

foo {
  bar {
    baz = 2
  }
}
%{"foo" => [%{"bar" => %{"baz" => 1}}, %{"bar" => %{"baz" => 2}}]}
foo {
  bar {
    baz = 1
  }
  bar {
    baz = 2
  }
}

foo { 
  bar {
    baz = 2
  }
}
%{
    "foo" => [
      %{"bar" => [%{"baz" => 1}, %{"baz" => 2}]},
      %{"bar" => %{"baz" => 2}}
    ]
  }

Looks ok?

jclem commented 1 year ago

Yup, looks right! Thanks—I'll leave the issue-closing to you 😄

drowzy commented 1 year ago

😁