Addressing Section List Values without an Index
This is a special behavior in ELCL that applies only in configuration documents — not in parser APIs. If a name path refers to a section list, and the next segment in the path is a regular name rather than an index, the path automatically points to the last entry in the list.
In other words:
In a configuration file, when no index is given,
the next name in the path refers to a child value or section inside the last added entry of the section list.
Example: Single Section List
The configuration below defines a section list named server.connection with two entries:
[main]
user: "example"
[server]
threads: 4
startup delay: 20 s
*[server.connection]
port: 8080
interface: "web"
*[server.connection]
port: 9000
interface: "api"
[server.backend.filter]
reject: "bad"
accept: "good"
The resulting value tree shows how the name path server.connection.port resolves:
Path: server.connection.port
● (root)                    <== Document ( size=2 ) 
┠── [main]                  <== SectionWithNames ( size=1 ) 
┃   └── user                    <== Text ( "example" ) 
┗━━ [server]                <== SectionWithNames ( size=4 ) 
    ┠── [backend]               <== IntermediateSection (  ) 
    ┃   └── [filter]                <== SectionWithNames ( size=2 ) 
    ┃       ├── accept                  <== Text ( "good" ) 
    ┃       └── reject                  <== Text ( "bad" ) 
    ┡━━ *[connection]           <== SectionList ( size=2 ) 
    │   ┠── [0]                     <== SectionWithNames ( size=2 ) 
    │   ┃   ├── interface               <== Text ( "web" ) 
    │   ┃   └── port                    <== Integer ( 8080 ) 
    │   ┗━━ [1]                     <== SectionWithNames ( size=2 ) 
    │       ┠── interface               <== Text ( "api" ) 
    │       ┗━━ port                    <== Integer ( 9000 ) 
    ├── startup_delay           <== TimeDelta ( Not supported ) 
    └── threads                 <== Integer ( 4 ) Here, the path server.connection.port points to the port value of the last entry in the connection list — the one that holds the value 9000.
Why This Rule Exists
At first glance, this rule may seem unusual — especially when working with a single-level list. However, it becomes intuitive and very useful in nested list structures, such as when building hierarchies dynamically.
Example: Nested Section Lists
Here is a configuration with nested section lists. Each place may optionally define a list of tree sections:
---*[place]*---
name: "example01"
---*[place]*---
name: "example02"
*[place.tree]
fruit: "apple"
*[place.tree]
fruit: "pear"
---*[place]*---
name: "example03"
*[place.tree]
fruit: "cherry"
*[place.tree]
fruit: "apricot"
The configuration expands into the following value tree:
● (root)                    <== Document ( size=1 ) 
└── *[place]                <== SectionList ( size=3 ) 
    ├── [0]                     <== SectionWithNames ( size=1 ) 
    │   └── name                    <== Text ( "example01" ) 
    ├── [1]                     <== SectionWithNames ( size=2 ) 
    │   ├── *[tree]                 <== SectionList ( size=2 ) 
    │   │   ├── [0]                     <== SectionWithNames ( size=1 ) 
    │   │   │   └── fruit                   <== Text ( "apple" ) 
    │   │   └── [1]                     <== SectionWithNames ( size=1 ) 
    │   │       └── fruit                   <== Text ( "pear" ) 
    │   └── name                    <== Text ( "example02" ) 
    └── [2]                     <== SectionWithNames ( size=2 ) 
        ├── *[tree]                 <== SectionList ( size=2 ) 
        │   ├── [0]                     <== SectionWithNames ( size=1 ) 
        │   │   └── fruit                   <== Text ( "cherry" ) 
        │   └── [1]                     <== SectionWithNames ( size=1 ) 
        │       └── fruit                   <== Text ( "apricot" ) 
        └── name                    <== Text ( "example03" ) The tree shows how entries are added to the place list and how tree sections belong to the last added place.
Let’s highlight the relevant part:
13---*[place]*---
14name: "example03"
15
16*[place.tree]
17fruit: "cherry"
Even though place is a list, we didn’t provide an index in place.tree. Therefore, the configuration implicitly attaches the tree entry to the last place — in this case, the one with name example03.
Note
In this example, the full path place.tree is used for clarity. In real-world configurations, it’s typically better to use relative name paths like .tree instead.
Clarifying Name Path Semantics
In configuration files, name paths like
place.treeautomatically refer to the last entry in a list when no index is given.In parser APIs, this automatic behavior may or may not apply. Instead, you get explicit control over which element in a list you want to access.