readNodes reads nodes from the currently parsed block. The lexer's cursor should point to the opening brace name arg0 arg1 { #< this one c0 c1 } To stay consistent with readNode after this function returns the lexer's cursor points to the last token of the black (closing brace).
()
| 217 | // To stay consistent with readNode after this function returns the lexer's cursor points |
| 218 | // to the last token of the black (closing brace). |
| 219 | func (ctx *parseContext) readNodes() ([]Node, error) { |
| 220 | // It is not 'var res []Node' because we want empty |
| 221 | // but non-nil Children slice for empty braces. |
| 222 | res := []Node{} |
| 223 | |
| 224 | if ctx.nesting > 255 { |
| 225 | return res, ctx.Err("nesting limit reached") |
| 226 | } |
| 227 | |
| 228 | ctx.nesting++ |
| 229 | |
| 230 | var requireNewLine bool |
| 231 | // This loop iterates over logical lines. |
| 232 | // Here are some examples, '#' is placed before token where cursor is when |
| 233 | // another iteration of this loop starts. |
| 234 | // |
| 235 | // #a |
| 236 | // #a b |
| 237 | // #a b { |
| 238 | // #ac aa |
| 239 | // #} |
| 240 | // #aa bbb bbb \ |
| 241 | // ccc ccc |
| 242 | // #a b { #ac aa } |
| 243 | // |
| 244 | // As can be seen by the latest example, sometimes such logical line might |
| 245 | // not be terminated by an actual LF character and so this needs to be |
| 246 | // handled carefully. |
| 247 | // |
| 248 | // Note that if the '}' is on the same physical line, it is currently |
| 249 | // included as the part of the logical line, that is: |
| 250 | // #a b { #ac aa } |
| 251 | // ^------- that's the logical line |
| 252 | // #c d |
| 253 | // ^--- that's the next logical line |
| 254 | // This is handled by the "edge case" branch inside the loop. |
| 255 | for { |
| 256 | if requireNewLine { |
| 257 | if !ctx.NextLine() { |
| 258 | // If we can't advance cursor even without Line constraint - |
| 259 | // that's EOF. |
| 260 | if !ctx.Next() { |
| 261 | return res, nil |
| 262 | } |
| 263 | return res, ctx.Err("newline is required after closing brace") |
| 264 | } |
| 265 | } else if !ctx.Next() { |
| 266 | break |
| 267 | } |
| 268 | |
| 269 | // name arg0 arg1 { |
| 270 | // c0 |
| 271 | // c1 |
| 272 | // } |
| 273 | // ^ called when we hit } on separate line, |
| 274 | // This means block we hit end of our block. |
| 275 | if ctx.Val() == "}" { |
| 276 | ctx.nesting-- |