parser: move tree-aware location functions to Tree/Node

This commit is contained in:
Joao Paulo Magalhaes
2025-08-31 11:51:36 +01:00
parent 6b80ff6419
commit 44ef17ae66
8 changed files with 231 additions and 196 deletions

View File

@@ -880,7 +880,7 @@ I am something: indeed
// ... and use it when querying
ryml::ConstNodeRef subject_node = tree2["bar"][1];
CHECK(subject_node.val() == "30");
ryml::Location loc = parser.location(subject_node);
ryml::Location loc = subject_node.location(parser);
CHECK(parser.location_contents(loc).begins_with("30"));
CHECK(loc.line == 1u);
CHECK(loc.col == 9u);
@@ -5284,7 +5284,7 @@ foo: [one, [two, three]]
// Now the structure will be built during parsing:
ryml::Tree tree = parse_in_arena(&parser, "source.yml", yaml);
// After this, we are ready to query the location from the parser:
ryml::Location loc = parser.location(tree.rootref());
ryml::Location loc = tree.rootref().location(parser);
// As for the complexity of the query: for large buffers it is
// O(log(numlines)). For short source buffers (30 lines and less),
// it is O(numlines), as a plain linear search is faster in this
@@ -5295,31 +5295,31 @@ foo: [one, [two, three]]
CHECK(loc.col == 0u);
// on the next call, we only pay O(log(numlines)) because the
// rebuild is already available:
loc = parser.location(tree["aa"]);
loc = tree["aa"].location(parser);
CHECK(parser.location_contents(loc).begins_with("aa"));
CHECK(loc.offset == 2u);
CHECK(loc.line == 1u);
CHECK(loc.col == 0u);
// KEYSEQ in flow style: points at the key
loc = parser.location(tree["foo"]);
loc = tree["foo"].location(parser);
CHECK(parser.location_contents(loc).begins_with("foo"));
CHECK(loc.offset == 16u);
CHECK(loc.line == 2u);
CHECK(loc.col == 0u);
loc = parser.location(tree["foo"][0]);
loc = tree["foo"][0].location(parser);
CHECK(parser.location_contents(loc).begins_with("one"));
CHECK(loc.line == 2u);
CHECK(loc.col == 6u);
// SEQ in flow style: location points at the opening '[' (there's no key)
loc = parser.location(tree["foo"][1]);
loc = tree["foo"][1].location(parser);
CHECK(parser.location_contents(loc).begins_with("["));
CHECK(loc.line == 2u);
CHECK(loc.col == 11u);
loc = parser.location(tree["foo"][1][0]);
loc = tree["foo"][1][0].location(parser);
CHECK(parser.location_contents(loc).begins_with("two"));
CHECK(loc.line == 2u);
CHECK(loc.col == 12u);
loc = parser.location(tree["foo"][1][1]);
loc = tree["foo"][1][1].location(parser);
CHECK(parser.location_contents(loc).begins_with("three"));
CHECK(loc.line == 2u);
CHECK(loc.col == 17u);
@@ -5332,8 +5332,8 @@ foo: [one, [two, three]]
ryml::Tree docval = parse_in_arena(&parser, "docval.yaml", "this is a docval");
// From now on, none of the locations from the previous tree can
// be queried:
//loc = parser.location(tree.rootref()); // ERROR, undefined behavior
loc = parser.location(docval.rootref()); // OK. this is the latest tree from this parser
//loc = tree.rootref().location(parser); // ERROR, undefined behavior
loc = docval.rootref().location(parser); // OK. this is the latest tree from this parser
CHECK(parser.location_contents(loc).begins_with("this is a docval"));
CHECK(loc.line == 0u);
CHECK(loc.col == 0u);
@@ -5361,63 +5361,63 @@ seq with key:
// points at the first child's key. For example, in this case
// the root does not have a key, so its location is taken
// to be at the first child:
loc = parser.location(tree2.rootref());
loc = tree2.rootref().location(parser);
CHECK(parser.location_contents(loc).begins_with("a new"));
CHECK(loc.offset == 1u);
CHECK(loc.line == 1u);
CHECK(loc.col == 0u);
// note the first child points exactly at the same place:
loc = parser.location(tree2["a new"]);
loc = tree2["a new"].location(parser);
CHECK(parser.location_contents(loc).begins_with("a new"));
CHECK(loc.offset == 1u);
CHECK(loc.line == 1u);
CHECK(loc.col == 0u);
loc = parser.location(tree2["to"]);
loc = tree2["to"].location(parser);
CHECK(parser.location_contents(loc).begins_with("to"));
CHECK(loc.line == 2u);
CHECK(loc.col == 0u);
// but of course, if the block-style map is a KEYMAP, then the
// location is the map's key, and not the first child's key:
loc = parser.location(tree2["map with key"]);
loc = tree2["map with key"].location(parser);
CHECK(parser.location_contents(loc).begins_with("map with key"));
CHECK(loc.line == 3u);
CHECK(loc.col == 0u);
loc = parser.location(tree2["map with key"]["first"]);
loc = tree2["map with key"]["first"].location(parser);
CHECK(parser.location_contents(loc).begins_with("first"));
CHECK(loc.line == 4u);
CHECK(loc.col == 2u);
loc = parser.location(tree2["map with key"]["second"]);
loc = tree2["map with key"]["second"].location(parser);
CHECK(parser.location_contents(loc).begins_with("second"));
CHECK(loc.line == 5u);
CHECK(loc.col == 2u);
// same thing for KEYSEQ:
loc = parser.location(tree2["seq with key"]);
loc = tree2["seq with key"].location(parser);
CHECK(parser.location_contents(loc).begins_with("seq with key"));
CHECK(loc.line == 6u);
CHECK(loc.col == 0u);
loc = parser.location(tree2["seq with key"][0]);
loc = tree2["seq with key"][0].location(parser);
CHECK(parser.location_contents(loc).begins_with("first value"));
CHECK(loc.line == 7u);
CHECK(loc.col == 4u);
loc = parser.location(tree2["seq with key"][1]);
loc = tree2["seq with key"][1].location(parser);
CHECK(parser.location_contents(loc).begins_with("second value"));
CHECK(loc.line == 8u);
CHECK(loc.col == 4u);
// SEQ nested in SEQ: container location points at the first child's "- " dash
loc = parser.location(tree2["seq with key"][2]);
loc = tree2["seq with key"][2].location(parser);
CHECK(parser.location_contents(loc).begins_with("- nested first value"));
CHECK(loc.line == 10u);
CHECK(loc.col == 4u);
loc = parser.location(tree2["seq with key"][2][0]);
loc = tree2["seq with key"][2][0].location(parser);
CHECK(parser.location_contents(loc).begins_with("nested first value"));
CHECK(loc.line == 10u);
CHECK(loc.col == 6u);
// MAP nested in SEQ: same as above: point to key
loc = parser.location(tree2["seq with key"][3]);
loc = tree2["seq with key"][3].location(parser);
CHECK(parser.location_contents(loc).begins_with("nested first: "));
CHECK(loc.line == 13u);
CHECK(loc.col == 4u);
loc = parser.location(tree2["seq with key"][3][0]);
loc = tree2["seq with key"][3][0].location(parser);
CHECK(parser.location_contents(loc).begins_with("nested first: "));
CHECK(loc.line == 13u);
CHECK(loc.col == 4u);