+/**
+ * Adds a token to the token anchor set (a multi-set).
+ */
+static void add_anchor_token(int token_type) {
+ assert(0 <= token_type && token_type < T_LAST_TOKEN);
+ ++token_anchor_set[token_type];
+}
+
+/**
+ * Remove a token from the token anchor set (a multi-set).
+ */
+static void rem_anchor_token(int token_type) {
+ assert(0 <= token_type && token_type < T_LAST_TOKEN);
+ --token_anchor_set[token_type];
+}
+
+static bool at_anchor(void) {
+ if(token.type < 0)
+ return false;
+ return token_anchor_set[token.type];
+}
+
+/**
+ * Eat tokens until a matching token is found.
+ */
+static void eat_until_matching_token(int type) {
+ unsigned parenthesis_count = 0;
+ unsigned brace_count = 0;
+ unsigned bracket_count = 0;
+ int end_token = type;
+
+ if(type == '(')
+ end_token = ')';
+ else if(type == '{')
+ end_token = '}';
+ else if(type == '[')
+ end_token = ']';
+
+ while(token.type != end_token ||
+ (parenthesis_count > 0 || brace_count > 0 || bracket_count > 0)) {
+
+ switch(token.type) {
+ case T_EOF: return;
+ case '(': ++parenthesis_count; break;
+ case '{': ++brace_count; break;
+ case '[': ++bracket_count; break;
+ case ')':
+ if(parenthesis_count > 0)
+ --parenthesis_count;
+ break;
+ case '}':
+ if(brace_count > 0)
+ --brace_count;
+ break;
+ case ']':
+ if(bracket_count > 0)
+ --bracket_count;
+ break;
+ default:
+ break;
+ }
+ next_token();
+ }
+}
+
+/**
+ * Eat input tokens until an anchor is found.
+ */
+static void eat_until_anchor(void) {
+ if(token.type == T_EOF)
+ return;
+ while(token_anchor_set[token.type] == 0) {
+ if(token.type == '(' || token.type == '{' || token.type == '[')
+ eat_until_matching_token(token.type);
+ if(token.type == T_EOF)
+ break;
+ next_token();
+ }
+}
+
+static void eat_block(void) {
+ eat_until_matching_token('{');
+ if(token.type == '}')
+ next_token();
+}
+
+/**
+ * eat all token until a ';' is reached
+ * or a stop token is found.
+ */
+static void eat_statement(void) {
+ eat_until_matching_token(';');
+ if(token.type == ';')
+ next_token();
+}
+