Expose quantifiers per pattern, instead of merging for all patterns in a query

This commit is contained in:
Hendrik van Antwerpen 2021-12-07 16:17:22 +01:00
parent 1d513bcf67
commit a1a241b013
5 changed files with 108 additions and 51 deletions

View file

@ -675,7 +675,11 @@ extern "C" {
#[doc = " Get the quantifier of the query's captures, or one of the query's string"]
#[doc = " literals. Each capture and string is associated with a numeric id based"]
#[doc = " on the order that it appeared in the query's source."]
pub fn ts_query_capture_quantifier_for_id(arg1: *const TSQuery, id: u32) -> TSQuantifier;
pub fn ts_query_capture_quantifier_for_id(
arg1: *const TSQuery,
pattern_id: u32,
capture_id: u32,
) -> TSQuantifier;
}
extern "C" {
pub fn ts_query_string_value_for_id(

View file

@ -98,7 +98,7 @@ pub struct TreeCursor<'a>(ffi::TSTreeCursor, PhantomData<&'a ()>);
pub struct Query {
ptr: NonNull<ffi::TSQuery>,
capture_names: Vec<String>,
capture_quantifiers: Vec<CaptureQuantifier>,
capture_quantifiers: Vec<Vec<CaptureQuantifier>>,
text_predicates: Vec<Box<[TextPredicate]>>,
property_settings: Vec<Box<[QueryProperty]>>,
property_predicates: Vec<Box<[(QueryProperty, bool)]>>,
@ -108,19 +108,21 @@ pub struct Query {
/// A quantifier for captures
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum CaptureQuantifier {
One,
OneOrMore,
Zero,
ZeroOrOne,
ZeroOrMore,
One,
OneOrMore,
}
impl From<ffi::TSQuantifier> for CaptureQuantifier {
fn from(value: ffi::TSQuantifier) -> Self {
match value {
ffi::TSQuantifier_One => CaptureQuantifier::One,
ffi::TSQuantifier_OneOrMore => CaptureQuantifier::OneOrMore,
ffi::TSQuantifier_Zero => CaptureQuantifier::Zero,
ffi::TSQuantifier_ZeroOrOne => CaptureQuantifier::ZeroOrOne,
ffi::TSQuantifier_ZeroOrMore => CaptureQuantifier::ZeroOrMore,
ffi::TSQuantifier_One => CaptureQuantifier::One,
ffi::TSQuantifier_OneOrMore => CaptureQuantifier::OneOrMore,
_ => panic!("Unrecognized quantifier: {}", value),
}
}
@ -1328,7 +1330,7 @@ impl Query {
let mut result = Query {
ptr: unsafe { NonNull::new_unchecked(ptr) },
capture_names: Vec::with_capacity(capture_count as usize),
capture_quantifiers: Vec::with_capacity(capture_count as usize),
capture_quantifiers: Vec::with_capacity(pattern_count as usize),
text_predicates: Vec::with_capacity(pattern_count),
property_predicates: Vec::with_capacity(pattern_count),
property_settings: Vec::with_capacity(pattern_count),
@ -1344,11 +1346,21 @@ impl Query {
let name = slice::from_raw_parts(name, length as usize);
let name = str::from_utf8_unchecked(name);
result.capture_names.push(name.to_string());
let quantifier = ffi::ts_query_capture_quantifier_for_id(ptr, i);
result.capture_quantifiers.push(quantifier.into());
}
}
// Build
for i in 0..pattern_count {
let mut capture_quantifiers = Vec::with_capacity(capture_count as usize);
for j in 0..capture_count {
unsafe {
let quantifier = ffi::ts_query_capture_quantifier_for_id(ptr, i as u32, j);
capture_quantifiers.push(quantifier.into());
}
}
result.capture_quantifiers.push(capture_quantifiers);
}
// Build a vector of strings to represent literal values used in predicates.
let string_values = (0..string_count)
.map(|i| unsafe {
@ -1550,8 +1562,8 @@ impl Query {
}
/// Get the quantifiers of the captures used in the query.
pub fn capture_quantifiers(&self) -> &[CaptureQuantifier] {
&self.capture_quantifiers
pub fn capture_quantifiers(&self, index: usize) -> &[CaptureQuantifier] {
&self.capture_quantifiers[index]
}
/// Get the index for a given capture name.

View file

@ -756,8 +756,10 @@ const char *ts_query_capture_name_for_id(
*/
TSQuantifier ts_query_capture_quantifier_for_id(
const TSQuery *,
uint32_t id
uint32_t pattern_id,
uint32_t capture_id
);
const char *ts_query_string_value_for_id(
const TSQuery *,
uint32_t id,

View file

@ -267,7 +267,7 @@ typedef struct {
*/
struct TSQuery {
SymbolTable captures;
CaptureQuantifiers capture_quantifiers;
Array(CaptureQuantifiers) capture_quantifiers;
SymbolTable predicate_values;
Array(QueryStep) steps;
Array(PatternEntry) pattern_map;
@ -2500,7 +2500,7 @@ TSQuery *ts_query_new(
.steps = array_new(),
.pattern_map = array_new(),
.captures = symbol_table_new(),
.capture_quantifiers = capture_quantifiers_new(),
.capture_quantifiers = array_new(),
.predicate_values = symbol_table_new(),
.predicate_steps = array_new(),
.patterns = array_new(),
@ -2525,7 +2525,8 @@ TSQuery *ts_query_new(
.predicate_steps = (Slice) {.offset = start_predicate_step_index},
.start_byte = stream_offset(&stream),
}));
*error_type = ts_query__parse_pattern(self, &stream, 0, false, &self->capture_quantifiers);
CaptureQuantifiers capture_quantifiers = capture_quantifiers_new();
*error_type = ts_query__parse_pattern(self, &stream, 0, false, &capture_quantifiers);
array_push(&self->steps, query_step__new(0, PATTERN_DONE_MARKER, false));
QueryPattern *pattern = array_back(&self->patterns);
@ -2537,10 +2538,14 @@ TSQuery *ts_query_new(
if (*error_type) {
if (*error_type == PARENT_DONE) *error_type = TSQueryErrorSyntax;
*error_offset = stream_offset(&stream);
capture_quantifiers_delete(&capture_quantifiers);
ts_query_delete(self);
return NULL;
}
// Maintain a list of capture quantifiers for each pattern
array_push(&self->capture_quantifiers, capture_quantifiers);
// Maintain a map that can look up patterns for a given root symbol.
uint16_t wildcard_root_alternative_index = NONE;
for (;;) {
@ -2616,7 +2621,11 @@ void ts_query_delete(TSQuery *self) {
array_delete(&self->negated_fields);
symbol_table_delete(&self->captures);
symbol_table_delete(&self->predicate_values);
capture_quantifiers_delete(&self->capture_quantifiers);
for (uint32_t index = 0; index < self->capture_quantifiers.size; index++) {
CaptureQuantifiers *capture_quantifiers = array_get(&self->capture_quantifiers, index);
capture_quantifiers_delete(capture_quantifiers);
}
array_delete(&self->capture_quantifiers);
ts_free(self);
}
}
@ -2643,9 +2652,11 @@ const char *ts_query_capture_name_for_id(
TSQuantifier ts_query_capture_quantifier_for_id(
const TSQuery *self,
uint32_t index
uint32_t pattern_index,
uint32_t capture_index
) {
return capture_quantifier_for_id(&self->capture_quantifiers, index);
CaptureQuantifiers *capture_quantifiers = array_get(&self->capture_quantifiers, pattern_index);
return capture_quantifier_for_id(capture_quantifiers, capture_index);
}
const char *ts_query_string_value_for_id(