Symbols without aliases should be used for lookahead

This commit is contained in:
Daumantas Kavolis 2023-06-15 15:55:32 +03:00
parent 7267384970
commit 1f52f2f1dc
9 changed files with 115 additions and 7 deletions

View file

@ -288,6 +288,14 @@ extern "C" {
#[doc = " Get the node's language."]
pub fn ts_node_language(arg1: TSNode) -> *const TSLanguage;
}
extern "C" {
#[doc = " Get the node's type as it appears in the grammar ignoring aliases as a\n null-terminated string."]
pub fn ts_node_grammar_type(arg1: TSNode) -> *const ::std::os::raw::c_char;
}
extern "C" {
#[doc = " Get the node's type as a numerical id as it appears in the grammar ignoring\n aliases. This should be used in `ts_language_next_state` instead of\n `ts_node_symbol`."]
pub fn ts_node_grammar_symbol(arg1: TSNode) -> TSSymbol;
}
extern "C" {
#[doc = " Get the node's start byte."]
pub fn ts_node_start_byte(arg1: TSNode) -> u32;
@ -340,6 +348,10 @@ extern "C" {
#[doc = " Get this node's parse state."]
pub fn ts_node_parse_state(arg1: TSNode) -> TSStateId;
}
extern "C" {
#[doc = " Get the parse state after this node."]
pub fn ts_node_next_parse_state(arg1: TSNode) -> TSStateId;
}
extern "C" {
#[doc = " Get the node's immediate parent."]
pub fn ts_node_parent(arg1: TSNode) -> TSNode;
@ -681,7 +693,7 @@ extern "C" {
pub fn ts_language_version(arg1: *const TSLanguage) -> u32;
}
extern "C" {
#[doc = " Get the next parse state. Combine this with lookahead iterators to generate\n completion suggestions or valid symbols in error nodes."]
#[doc = " Get the next parse state. Combine this with lookahead iterators to generate\n completion suggestions or valid symbols in error nodes. Use\n `ts_node_grammar_symbol` for valid symbols."]
pub fn ts_language_next_state(
arg1: *const TSLanguage,
arg2: TSStateId,

View file

@ -349,6 +349,11 @@ impl Language {
/// Get the next parse state. Combine this with [lookahead_iterator] to
/// generate completion suggestions or valid symbols in error nodes.
///
/// Example:
/// ```
/// let state = language.next_state(node.parse_state(), node.grammar_id());
/// ```
#[doc(alias = "ts_language_next_state")]
pub fn next_state(&self, state: u16, id: u16) -> u16 {
unsafe { ffi::ts_language_next_state(self.0, state, id) }
@ -872,6 +877,13 @@ impl<'tree> Node<'tree> {
unsafe { ffi::ts_node_symbol(self.0) }
}
/// Get the node's type as a numerical id as it appears in the grammar
/// ignoring aliases.
#[doc(alias = "ts_node_grammar_symbol")]
pub fn grammar_id(&self) -> u16 {
unsafe { ffi::ts_node_grammar_symbol(self.0) }
}
/// Get this node's type as a string.
#[doc(alias = "ts_node_type")]
pub fn kind(&self) -> &'static str {
@ -880,6 +892,15 @@ impl<'tree> Node<'tree> {
.unwrap()
}
/// Get this node's symbol name as it appears in the grammar ignoring
/// aliases as a string.
#[doc(alias = "ts_node_grammar_type")]
pub fn grammar_name(&self) -> &'static str {
unsafe { CStr::from_ptr(ffi::ts_node_grammar_type(self.0)) }
.to_str()
.unwrap()
}
/// Get the [Language] that was used to parse this node's syntax tree.
#[doc(alias = "ts_node_language")]
pub fn language(&self) -> Language {
@ -931,6 +952,12 @@ impl<'tree> Node<'tree> {
unsafe { ffi::ts_node_parse_state(self.0) }
}
/// Get the parse state after this node.
#[doc(alias = "ts_node_next_parse_state")]
pub fn next_parse_state(&self) -> u16 {
unsafe { ffi::ts_node_next_parse_state(self.0) }
}
/// Check if this node is *missing*.
///
/// Missing nodes are inserted by the parser in order to recover from certain kinds of

View file

@ -361,6 +361,11 @@ uint16_t ts_node_symbol_wasm(const TSTree *tree) {
return ts_node_symbol(node);
}
uint16_t ts_node_grammar_symbol_wasm(const TSTree *tree) {
TSNode node = unmarshal_node(tree);
return ts_node_grammar_symbol(node);
}
uint32_t ts_node_child_count_wasm(const TSTree *tree) {
TSNode node = unmarshal_node(tree);
return ts_node_child_count(node);
@ -621,6 +626,11 @@ uint16_t ts_node_parse_state_wasm(const TSTree *tree) {
return ts_node_parse_state(node);
}
uint16_t ts_node_next_parse_state_wasm(const TSTree *tree) {
TSNode node = unmarshal_node(tree);
return ts_node_next_parse_state(node);
}
/******************/
/* Section - Query */
/******************/

View file

@ -209,10 +209,19 @@ class Node {
return C._ts_node_symbol_wasm(this.tree[0]);
}
get grammarId() {
marshalNode(this);
return C._ts_node_grammar_symbol_wasm(this.tree[0]);
}
get type() {
return this.tree.language.types[this.typeId] || 'ERROR';
}
get grammarType() {
return this.tree.language.types[this.grammarId] || 'ERROR';
}
get endPosition() {
marshalNode(this);
C._ts_node_end_point_wasm(this.tree[0]);
@ -233,6 +242,11 @@ class Node {
return C._ts_node_parse_state_wasm(this.tree[0]);
}
get nextParseState() {
marshalNode(this);
return C._ts_node_next_parse_state_wasm(this.tree[0]);
}
isNamed() {
marshalNode(this);
return C._ts_node_is_named_wasm(this.tree[0]) === 1;

View file

@ -59,6 +59,7 @@
"_ts_node_is_missing_wasm",
"_ts_node_is_named_wasm",
"_ts_node_parse_state_wasm",
"_ts_node_next_parse_state_wasm",
"_ts_node_named_child_count_wasm",
"_ts_node_named_child_wasm",
"_ts_node_named_children_wasm",
@ -72,6 +73,7 @@
"_ts_node_start_index_wasm",
"_ts_node_start_point_wasm",
"_ts_node_symbol_wasm",
"_ts_node_grammar_symbol_wasm",
"_ts_node_to_string_wasm",
"_ts_parser_delete",
"_ts_parser_enable_logger_wasm",

View file

@ -327,7 +327,7 @@ describe("Node", () => {
});
describe(".parseState", () => {
const text = "10 * 5";
const text = "10 / 5";
it(`returns node parse state ids`, async () => {
tree = await parser.parse(text)
@ -335,9 +335,13 @@ describe("Node", () => {
const [numerator, slash, denominator] = quotientNode.children;
assert.equal(tree.rootNode.parseState, 0);
assert.equal(numerator.parseState, 1);
assert.equal(slash.parseState, 553);
assert.equal(denominator.parseState, 185);
// parse states will change on any change to the grammar so test that it
// returns something instead
assert.isAbove(numerator.parseState, 0);
assert.isAbove(numerator.nextParseState, 0);
assert.isAbove(slash.parseState, 0);
assert.isAbove(denominator.parseState, 0);
assert.isAbove(denominator.nextParseState, 0);
})
});

View file

@ -55,11 +55,14 @@ declare module 'web-tree-sitter' {
) => string | null;
export interface SyntaxNode {
id: number;
typeId: number;
grammarId: number;
tree: Tree;
type: string;
grammarType: string;
text: string;
parseState: number;
nextParseState: number;
startPosition: Point;
endPosition: Point;
startIndex: number;

View file

@ -445,6 +445,19 @@ TSSymbol ts_node_symbol(TSNode);
*/
const TSLanguage *ts_node_language(TSNode);
/**
* Get the node's type as it appears in the grammar ignoring aliases as a
* null-terminated string.
*/
const char *ts_node_grammar_type(TSNode);
/**
* Get the node's type as a numerical id as it appears in the grammar ignoring
* aliases. This should be used in `ts_language_next_state` instead of
* `ts_node_symbol`.
*/
TSSymbol ts_node_grammar_symbol(TSNode);
/**
* Get the node's start byte.
*/
@ -519,6 +532,11 @@ bool ts_node_is_error(TSNode);
*/
TSStateId ts_node_parse_state(TSNode);
/**
* Get the parse state after this node.
*/
TSStateId ts_node_next_parse_state(TSNode);
/**
* Get the node's immediate parent.
*/
@ -1025,7 +1043,8 @@ uint32_t ts_language_version(const TSLanguage *);
/**
* Get the next parse state. Combine this with lookahead iterators to generate
* completion suggestions or valid symbols in error nodes.
* completion suggestions or valid symbols in error nodes. Use
* `ts_node_grammar_symbol` for valid symbols.
*/
TSStateId ts_language_next_state(const TSLanguage *, TSStateId, TSSymbol);

View file

@ -429,6 +429,15 @@ const TSLanguage *ts_node_language(TSNode self) {
return self.tree->language;
}
TSSymbol ts_node_grammar_symbol(TSNode self) {
return ts_subtree_symbol(ts_node__subtree(self));
}
const char *ts_node_grammar_type(TSNode self) {
TSSymbol symbol = ts_subtree_symbol(ts_node__subtree(self));
return ts_language_symbol_name(self.tree->language, symbol);
}
char *ts_node_string(TSNode self) {
return ts_subtree_string(ts_node__subtree(self), self.tree->language, false);
}
@ -477,6 +486,14 @@ TSStateId ts_node_parse_state(TSNode self) {
return ts_subtree_parse_state(ts_node__subtree(self));
}
TSStateId ts_node_next_parse_state(TSNode self) {
const TSLanguage *language = self.tree->language;
uint16_t state = ts_node_parse_state(self);
uint16_t symbol = ts_node_grammar_symbol(self);
return ts_language_next_state(language, state, symbol);
}
TSNode ts_node_parent(TSNode self) {
TSNode node = ts_tree_root_node(self.tree);
uint32_t end_byte = ts_node_end_byte(self);