2019-01-10 15:22:39 -08:00
|
|
|
#ifndef TREE_SITTER_PARSE_STACK_H_
|
|
|
|
|
#define TREE_SITTER_PARSE_STACK_H_
|
2015-05-25 20:21:13 -07:00
|
|
|
|
|
|
|
|
#ifdef __cplusplus
|
|
|
|
|
extern "C" {
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-01-04 17:33:34 -08:00
|
|
|
#include "./array.h"
|
|
|
|
|
#include "./subtree.h"
|
|
|
|
|
#include "./error_costs.h"
|
2016-04-02 22:18:44 -07:00
|
|
|
#include <stdio.h>
|
2015-05-25 20:21:13 -07:00
|
|
|
|
2015-09-18 18:04:52 -07:00
|
|
|
typedef struct Stack Stack;
|
2015-05-25 20:21:13 -07:00
|
|
|
|
2017-06-29 16:43:56 -07:00
|
|
|
typedef unsigned StackVersion;
|
2016-04-10 14:12:24 -07:00
|
|
|
#define STACK_VERSION_NONE ((StackVersion)-1)
|
2016-04-04 12:25:57 -07:00
|
|
|
|
2015-06-03 09:44:13 -07:00
|
|
|
typedef struct {
|
2018-05-10 15:11:14 -07:00
|
|
|
SubtreeArray subtrees;
|
2016-04-04 12:25:57 -07:00
|
|
|
StackVersion version;
|
2016-03-03 10:16:10 -08:00
|
|
|
} StackSlice;
|
2016-03-03 10:20:05 -08:00
|
|
|
typedef Array(StackSlice) StackSliceArray;
|
|
|
|
|
|
2016-03-03 11:05:37 -08:00
|
|
|
typedef struct {
|
2018-03-29 17:37:54 -07:00
|
|
|
Length position;
|
|
|
|
|
unsigned depth;
|
|
|
|
|
TSStateId state;
|
|
|
|
|
} StackSummaryEntry;
|
|
|
|
|
typedef Array(StackSummaryEntry) StackSummary;
|
2016-03-03 11:05:37 -08:00
|
|
|
|
2018-03-29 17:37:54 -07:00
|
|
|
// Create a stack.
|
2018-05-10 15:11:14 -07:00
|
|
|
Stack *ts_stack_new(SubtreePool *);
|
2015-06-03 09:44:13 -07:00
|
|
|
|
2018-03-29 17:37:54 -07:00
|
|
|
// Release the memory reserved for a given stack.
|
2015-09-18 18:04:52 -07:00
|
|
|
void ts_stack_delete(Stack *);
|
2015-05-25 20:21:13 -07:00
|
|
|
|
2018-03-29 17:37:54 -07:00
|
|
|
// Get the stack's current number of versions.
|
2016-11-14 12:15:24 -08:00
|
|
|
uint32_t ts_stack_version_count(const Stack *);
|
2015-05-25 20:21:13 -07:00
|
|
|
|
2018-03-29 17:37:54 -07:00
|
|
|
// Get the state at the top of the given version of the stack. If the stack is
|
|
|
|
|
// empty, this returns the initial state, 0.
|
|
|
|
|
TSStateId ts_stack_state(const Stack *, StackVersion);
|
2015-06-03 09:44:13 -07:00
|
|
|
|
2018-03-29 17:37:54 -07:00
|
|
|
// Get the last external token associated with a given version of the stack.
|
2018-09-17 13:12:13 -07:00
|
|
|
Subtree ts_stack_last_external_token(const Stack *, StackVersion);
|
2017-01-04 21:22:23 -08:00
|
|
|
|
2018-03-29 17:37:54 -07:00
|
|
|
// Set the last external token associated with a given version of the stack.
|
2018-09-17 13:12:13 -07:00
|
|
|
void ts_stack_set_last_external_token(Stack *, StackVersion, Subtree );
|
2016-09-01 10:04:20 -07:00
|
|
|
|
2018-03-29 17:37:54 -07:00
|
|
|
// Get the position of the given version of the stack within the document.
|
|
|
|
|
Length ts_stack_position(const Stack *, StackVersion);
|
2015-12-02 07:53:15 -08:00
|
|
|
|
2018-03-29 17:37:54 -07:00
|
|
|
// Push a tree and state onto the given version of the stack.
|
|
|
|
|
//
|
|
|
|
|
// This transfers ownership of the tree to the Stack. Callers that
|
|
|
|
|
// need to retain ownership of the tree for their own purposes should
|
|
|
|
|
// first retain the tree.
|
2018-09-17 13:12:13 -07:00
|
|
|
void ts_stack_push(Stack *, StackVersion, Subtree , bool, TSStateId);
|
2015-06-03 09:44:13 -07:00
|
|
|
|
2018-03-29 17:37:54 -07:00
|
|
|
// Pop the given number of entries from the given version of the stack. This
|
|
|
|
|
// operation can increase the number of stack versions by revealing multiple
|
|
|
|
|
// versions which had previously been merged. It returns an array that
|
|
|
|
|
// specifies the index of each revealed version and the trees that were
|
|
|
|
|
// removed from that version.
|
|
|
|
|
StackSliceArray ts_stack_pop_count(Stack *, StackVersion, uint32_t count);
|
2015-06-18 15:04:03 -07:00
|
|
|
|
2018-03-29 17:37:54 -07:00
|
|
|
// Remove an error at the top of the given version of the stack.
|
2018-05-10 15:11:14 -07:00
|
|
|
SubtreeArray ts_stack_pop_error(Stack *, StackVersion);
|
Simplify error recovery; eliminate recovery states
The previous approach to error recovery relied on special error-recovery
states in the parse table. For each token T, there was an error recovery
state in which the parser looked for *any* token that could follow T.
Unfortunately, sometimes the set of tokens that could follow T contained
conflicts. For example, in JS, the token '}' can be followed by the
open-ended 'template_chars' token, but also by ordinary tokens like
'identifier'. So with the old algorithm, when recovering from an
unexpected '}' token, the lexer had no way to distinguish identifiers
from template_chars.
This commit drops the error recovery states. Instead, when we encounter
an unexpected token T, we recover from the error by finding a previous
state S in the stack in which T would be valid, popping all of the nodes
after S, and wrapping them in an error.
This way, the lexer is always invoked in a normal parse state, in which
it is looking for a non-conflicting set of tokens. Eliminating the error
recovery states also shrinks the lex state machine significantly.
Signed-off-by: Rick Winfrey <rewinfrey@github.com>
2017-09-11 15:22:52 -07:00
|
|
|
|
2018-03-29 17:37:54 -07:00
|
|
|
// Remove any pending trees from the top of the given version of the stack.
|
|
|
|
|
StackSliceArray ts_stack_pop_pending(Stack *, StackVersion);
|
2016-03-31 12:03:07 -07:00
|
|
|
|
2018-03-29 17:37:54 -07:00
|
|
|
// Remove any all trees from the given version of the stack.
|
|
|
|
|
StackSliceArray ts_stack_pop_all(Stack *, StackVersion);
|
2016-04-04 11:44:45 -07:00
|
|
|
|
2018-04-02 11:57:26 -07:00
|
|
|
// Get the maximum number of tree nodes reachable from this version of the stack
|
|
|
|
|
// since the last error was detected.
|
2018-04-02 10:57:44 -07:00
|
|
|
unsigned ts_stack_node_count_since_error(const Stack *, StackVersion);
|
Simplify error recovery; eliminate recovery states
The previous approach to error recovery relied on special error-recovery
states in the parse table. For each token T, there was an error recovery
state in which the parser looked for *any* token that could follow T.
Unfortunately, sometimes the set of tokens that could follow T contained
conflicts. For example, in JS, the token '}' can be followed by the
open-ended 'template_chars' token, but also by ordinary tokens like
'identifier'. So with the old algorithm, when recovering from an
unexpected '}' token, the lexer had no way to distinguish identifiers
from template_chars.
This commit drops the error recovery states. Instead, when we encounter
an unexpected token T, we recover from the error by finding a previous
state S in the stack in which T would be valid, popping all of the nodes
after S, and wrapping them in an error.
This way, the lexer is always invoked in a normal parse state, in which
it is looking for a non-conflicting set of tokens. Eliminating the error
recovery states also shrinks the lex state machine significantly.
Signed-off-by: Rick Winfrey <rewinfrey@github.com>
2017-09-11 15:22:52 -07:00
|
|
|
|
2017-10-09 15:51:22 -07:00
|
|
|
int ts_stack_dynamic_precedence(Stack *, StackVersion);
|
|
|
|
|
|
2018-11-08 11:29:21 -08:00
|
|
|
bool ts_stack_has_advanced_since_error(const Stack *, StackVersion);
|
|
|
|
|
|
2018-03-29 17:37:54 -07:00
|
|
|
// Compute a summary of all the parse states near the top of the given
|
|
|
|
|
// version of the stack and store the summary for later retrieval.
|
2017-09-12 12:00:00 -07:00
|
|
|
void ts_stack_record_summary(Stack *, StackVersion, unsigned max_depth);
|
Simplify error recovery; eliminate recovery states
The previous approach to error recovery relied on special error-recovery
states in the parse table. For each token T, there was an error recovery
state in which the parser looked for *any* token that could follow T.
Unfortunately, sometimes the set of tokens that could follow T contained
conflicts. For example, in JS, the token '}' can be followed by the
open-ended 'template_chars' token, but also by ordinary tokens like
'identifier'. So with the old algorithm, when recovering from an
unexpected '}' token, the lexer had no way to distinguish identifiers
from template_chars.
This commit drops the error recovery states. Instead, when we encounter
an unexpected token T, we recover from the error by finding a previous
state S in the stack in which T would be valid, popping all of the nodes
after S, and wrapping them in an error.
This way, the lexer is always invoked in a normal parse state, in which
it is looking for a non-conflicting set of tokens. Eliminating the error
recovery states also shrinks the lex state machine significantly.
Signed-off-by: Rick Winfrey <rewinfrey@github.com>
2017-09-11 15:22:52 -07:00
|
|
|
|
2018-03-29 17:37:54 -07:00
|
|
|
// Retrieve a summary of all the parse states near the top of the
|
|
|
|
|
// given version of the stack.
|
Simplify error recovery; eliminate recovery states
The previous approach to error recovery relied on special error-recovery
states in the parse table. For each token T, there was an error recovery
state in which the parser looked for *any* token that could follow T.
Unfortunately, sometimes the set of tokens that could follow T contained
conflicts. For example, in JS, the token '}' can be followed by the
open-ended 'template_chars' token, but also by ordinary tokens like
'identifier'. So with the old algorithm, when recovering from an
unexpected '}' token, the lexer had no way to distinguish identifiers
from template_chars.
This commit drops the error recovery states. Instead, when we encounter
an unexpected token T, we recover from the error by finding a previous
state S in the stack in which T would be valid, popping all of the nodes
after S, and wrapping them in an error.
This way, the lexer is always invoked in a normal parse state, in which
it is looking for a non-conflicting set of tokens. Eliminating the error
recovery states also shrinks the lex state machine significantly.
Signed-off-by: Rick Winfrey <rewinfrey@github.com>
2017-09-11 15:22:52 -07:00
|
|
|
StackSummary *ts_stack_get_summary(Stack *, StackVersion);
|
|
|
|
|
|
2018-04-02 11:57:26 -07:00
|
|
|
// Get the total cost of all errors on the given version of the stack.
|
2017-09-13 16:38:15 -07:00
|
|
|
unsigned ts_stack_error_cost(const Stack *, StackVersion version);
|
2016-05-28 21:22:10 -07:00
|
|
|
|
2018-04-02 11:57:26 -07:00
|
|
|
// Merge the given two stack versions if possible, returning true
|
|
|
|
|
// if they were successfully merged and false otherwise.
|
2019-03-26 16:53:35 +01:00
|
|
|
bool ts_stack_merge(Stack *, StackVersion, StackVersion);
|
|
|
|
|
|
|
|
|
|
// Determine whether the given two stack versions can be merged.
|
2017-06-29 14:58:20 -07:00
|
|
|
bool ts_stack_can_merge(Stack *, StackVersion, StackVersion);
|
|
|
|
|
|
2018-04-02 09:47:01 -07:00
|
|
|
TSSymbol ts_stack_resume(Stack *, StackVersion);
|
|
|
|
|
|
|
|
|
|
void ts_stack_pause(Stack *, StackVersion, TSSymbol);
|
|
|
|
|
|
2016-06-02 14:04:48 -07:00
|
|
|
void ts_stack_halt(Stack *, StackVersion);
|
2016-04-10 14:12:24 -07:00
|
|
|
|
2018-04-02 09:47:01 -07:00
|
|
|
bool ts_stack_is_active(const Stack *, StackVersion);
|
|
|
|
|
|
|
|
|
|
bool ts_stack_is_paused(const Stack *, StackVersion);
|
|
|
|
|
|
|
|
|
|
bool ts_stack_is_halted(const Stack *, StackVersion);
|
2016-05-29 22:36:47 -07:00
|
|
|
|
2016-04-10 14:12:24 -07:00
|
|
|
void ts_stack_renumber_version(Stack *, StackVersion, StackVersion);
|
2015-05-25 20:21:13 -07:00
|
|
|
|
2017-06-29 14:58:20 -07:00
|
|
|
void ts_stack_swap_versions(Stack *, StackVersion, StackVersion);
|
|
|
|
|
|
2016-11-14 17:25:55 -08:00
|
|
|
StackVersion ts_stack_copy_version(Stack *, StackVersion);
|
2016-05-09 14:31:44 -07:00
|
|
|
|
2018-03-29 17:37:54 -07:00
|
|
|
// Remove the given version from the stack.
|
2016-04-04 12:25:57 -07:00
|
|
|
void ts_stack_remove_version(Stack *, StackVersion);
|
2015-07-08 17:34:21 -07:00
|
|
|
|
2015-09-18 18:04:52 -07:00
|
|
|
void ts_stack_clear(Stack *);
|
2015-06-18 15:04:03 -07:00
|
|
|
|
2018-04-08 13:49:20 -07:00
|
|
|
bool ts_stack_print_dot_graph(Stack *, const TSLanguage *, FILE *);
|
2018-03-29 17:50:07 -07:00
|
|
|
|
|
|
|
|
typedef void (*StackIterateCallback)(void *, TSStateId, uint32_t);
|
|
|
|
|
|
2015-05-25 20:21:13 -07:00
|
|
|
#ifdef __cplusplus
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
2019-01-10 15:22:39 -08:00
|
|
|
#endif // TREE_SITTER_PARSE_STACK_H_
|