row = parseTabularRow(rowContent, fields, arrayDelimiter, context);
result.add(row);
return true;
} else if (lineDepth > expectedRowDepth) {
- // Line is deeper than expected - might be nested content, skip it
+ // A line deeper than the row depth belongs to no scope (§14.2)
+ if (context.options.strict()) {
+ throw new IllegalArgumentException(
+ "Over-indented line after tabular rows at line " + (context.currentLine + 1));
+ }
+ // In non-strict mode, skip it
context.currentLine++;
return false;
}
@@ -306,36 +448,86 @@ private static boolean processTabularRow(final String line, final int lineDepth,
}
/**
- * Parses a tabular row into a Map using the provided keys.
- * Validates that the row uses the correct delimiter.
+ * Parses a tabular row into a Map using the provided field tree.
+ * A leaf field consumes the next cell; a nested field group materializes
+ * an object from its subfields (§9.3).
*
- * In strict mode, the number of values must exactly match the number of keys.
- * In lenient mode, excess values are silently dropped and missing values
- * result in omitted keys.
+ * In strict mode, the number of values must exactly match the leaf-field
+ * count. In lenient mode, excess values are silently dropped and missing
+ * values result in omitted keys.
*
* @param rowContent the row content to parse
- * @param keys the keys for the tabular array
+ * @param fields the field tree for the tabular array
* @param arrayDelimiter the type of delimiter used in the array
* @param context decode an object to deal with lines, delimiter and options
* @return a Map containing the parsed row values
*/
- private static Map parseTabularRow(final String rowContent, final List keys,
- final Delimiter arrayDelimiter, final DecodeContext context) {
+ static Map parseTabularRow(final String rowContent, final List fields,
+ final Delimiter arrayDelimiter, final DecodeContext context) {
final Map row = new LinkedHashMap<>();
final List