Problem:
Problem H:
Bug Hunt
In this problem, we consider a simple programming language that has only declarations of one-
dimensional integer arrays and assignment statements. The problem is to find a bug in the given
program.
The syntax of this language is given in BNF as follows:
where
<
new line
>
denotes a new line character (LF).
Characters used in a program are alphabetical letters, decimal digits,
=
,
[
,
]
and new line characters. No other characters appear in a program.
A declaration declares an array and specifies its length. Valid indices of an array of length
n
are integers between 0 and
n
- 1, inclusive. Note that the array names are case sensitive, i.e.
array
a
and array
A
are different arrays. The initial value of each element in the declared array is undefined.
For example, array
a
of length 10 and array
b
of length 5 are declared respectively as follows.
a[10]
b[5]
An expression evaluates to a non-negative integer. A
<
number
>
is interpreted as a decimal
integer. An
<
array_name
>
[<
expression
>]
evaluates to the value of the
<
expression
>
-th element of
the array. An assignment assigns the value denoted by the right hand side to the array element
specified by the left hand side.
Examples of assignments are as follows.
a[0]=3
a[1]=0
a[2]=a[a[1]]
a[a[0]]=a[1]
A program is executed from the first line, line by line. You can assume that an array is declared once and only once before any of its element is assigned or referred to.
Given a program, you are requested to find the following bugs.
An index of an array is invalid.
An array element that has not been assigned before is referred to in an assignment as an index of array or as the value to be assigned.
You can assume that other bugs, such as syntax errors, do not appear. You can also assume
that integers represented by
<
number
>
s are between 0 and 2
31
- 1 (= 2147483647), inclusive.
Input
The input consists of multiple datasets followed by a line which contains only a single '
.
' (period).
Each dataset consists of a program also followed by a line which contains only a single '
.
' (period).
A program does not exceed 1000 lines. Any line does not exceed 80 characters excluding a new
line character.
Output
For each program in the input, you should answer the line number of the assignment in which
the first bug appears. The line numbers start with 1 for each program. If the program does not
have a bug, you should answer zero. The output should not contain extra characters such as
spaces.
Sample Input
a[3]
a[0]=a[1]
.
x[1]
x[0]=x[0]
.
a[0]
a[0]=1
.
b[2]
b[0]=2
b[1]=b[b[0]]
b[0]=b[1]
.
g[2]
G[10]
g[0]=0
g[1]=G[0]
.
a[2147483647]
a[0]=1
B[2]
B[a[0]]=2
a[B[a[0]]]=3
a[2147483646]=a[2]
.
.
Output for the Sample Input
2
2
2
3
4
0

Submitted solutions:

code_snippet: #include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/tag_and_trait.hpp>
using namespace std;
using namespace __gnu_pbds;


struct custom_hash {
static uint64_t splitmix64(uint64_t x) {
x += 0x9e3779b97f4a7c15;
x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
return x ^ (x >> 31);
}

size_t operator()(uint64_t x) const {
static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
return splitmix64(x + FIXED_RANDOM);
}

size_t operator()(int x) const {
return splitmix64(x);
}

size_t operator()(const string& x) const {
uint64_t hash = 0;
for (char c : x) {
hash = hash * 31 + c;
}
return splitmix64(hash);
}

size_t operator()(const pair<int, int>& p) const {
return splitmix64(((uint64_t)p.first << 32) | (uint64_t)p.second);
}
};


template<typename T, typename S, typename Hash = custom_hash>
using hash_table = gp_hash_table<T, S, Hash>;
template<typename T, typename Hash = custom_hash>
using hash_set = gp_hash_table<T, null_type, Hash>;


class parser;


struct node {
int symbol_id;
string value;
vector<node*> values;

private:
const parser* parser_ptr;

public:
node(int s, const parser* p = nullptr) : symbol_id(s), value(""), parser_ptr(p) {}
node(int s, const string &v, const parser* p = nullptr) : symbol_id(s), value(v), parser_ptr(p) {}


void set_parser(const parser* p) {
parser_ptr = p;

for (auto child : values) {
if (child) {
child->set_parser(p);
}
}
}


string get_token_name() const;


void add_child(node* child) {
if (child && parser_ptr) {
child->set_parser(parser_ptr);
}
values.push_back(child);
}
};


struct LRItem {
int lhs;
vector<int> rhs;
int dot_pos;

LRItem(int l, const vector<int> &r, int d) : lhs(l), rhs(r), dot_pos(d) {}

bool operator==(const LRItem &other) const {
return lhs == other.lhs && rhs == other.rhs && dot_pos == other.dot_pos;
}

int next_symbol() const {
if (dot_pos < (int)rhs.size()) return rhs[dot_pos];
return -1;
}

bool is_complete() const {
return dot_pos >= (int)rhs.size();
}
};


struct LRItemHash {
size_t operator()(const LRItem &item) const {
size_t h1 = custom_hash{}(item.lhs);
size_t h2 = 0;
for (int s : item.rhs) {
h2 ^= custom_hash{}(s) + 0x9e3779b9 + (h2 << 6) + (h2 >> 2);
}
size_t h3 = custom_hash{}(item.dot_pos);
return h1 ^ (h2 << 1) ^ (h3 << 2);
}
};


enum class ActionType { SHIFT, REDUCE, ACCEPT, ERROR };

struct Action {
ActionType type;
int value;

Action() : type(ActionType::ERROR), value(-1) {}
Action(ActionType t, int v) : type(t), value(v) {}

string to_string() const {
switch (type) {
case ActionType::SHIFT: return "SHIFT " + std::to_string(value);
case ActionType::REDUCE: return "REDUCE " + std::to_string(value);
case ActionType::ACCEPT: return "ACCEPT";
case ActionType::ERROR: return "ERROR";
}
return "UNKNOWN";
}
};


struct Production {
int lhs;
vector<int> rhs;

Production(int l, const vector<int> &r) : lhs(l), rhs(r) {}
};

class parser {
private:

vector<string> id_to_name;
hash_table<string, int> name_to_id;


vector<string> terminal_patterns;
vector<int> terminal_order;
hash_set<int> terminals;
hash_set<int> nonterminals;
vector<Production> productions;


hash_table<int, hash_set<int>> first_sets;
hash_table<int, hash_set<int>> follow_sets;


vector<hash_set<LRItem, LRItemHash>> states;
hash_table<pair<int, int>, Action> action_table;
hash_table<pair<int, int>, int> goto_table;

int start_symbol_id = -1;
int augmented_start_id = -1;
bool debug_mode = false;


int get_or_create_symbol_id(const string &name) {
auto it = name_to_id.find(name);
if (it != name_to_id.end()) {
return it->second;
}
int id = (int)id_to_name.size();
id_to_name.push_back(name);
name_to_id[name] = id;
return id;
}

int get_or_create_symbol_id_const(const string &name) const {
auto it = name_to_id.find(name);
if (it != name_to_id.end()) {
return it->second;
}
return -1;
}


int resolve_symbol_reference(int symbol_id) const {
if (symbol_id == -1 || symbol_id >= (int)id_to_name.size()) return symbol_id;
const string &name = id_to_name[symbol_id];
if (name.length() > 0 && name[0] == '#') {
string actual_name = name.substr(1);
auto it = name_to_id.find(actual_name);
if (it != name_to_id.end()) {
return it->second;
}
}
return symbol_id;
}

bool is_terminal_symbol(int symbol_id) const {
int resolved_id = resolve_symbol_reference(symbol_id);
if (resolved_id == -1) return false;
return terminals.find(resolved_id) != terminals.end() && 
   nonterminals.find(resolved_id) == nonterminals.end();
}

bool is_nonterminal_symbol(int symbol_id) const {
int resolved_id = resolve_symbol_reference(symbol_id);
if (resolved_id == -1) return false;
return nonterminals.find(resolved_id) != nonterminals.end();
}


string production_to_string(const Production &prod) const {
string result = get_symbol_name(prod.lhs) + " ::= ";
for (int symbol_id : prod.rhs) {
int resolved_id = resolve_symbol_reference(symbol_id);
result += get_symbol_name(resolved_id) + " ";
}
return result;
}


vector<string> split_by_semicolon(const string &text) {
vector<string> rules;
stringstream ss(text);
string rule;

while (getline(ss, rule, ';')) {
rule.erase(0, rule.find_first_not_of(" \t\r\n"));
rule.erase(rule.find_last_not_of(" \t\r\n") + 1);

if (!rule.empty()) {
rules.push_back(rule);
}
}

return rules;
}



void parse_bnf(const string &bnf_text) {
regex terminal_pattern(R"(^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*?)\s*$)");
regex production_pattern(R"(^\s*([A-Za-z_][A-Za-z0-9_]*)\s*::=\s*(.*?)\s*$)");

vector<string> rules = split_by_semicolon(bnf_text);


for (size_t rule_idx = 0; rule_idx < rules.size(); rule_idx++) {
const string &rule = rules[rule_idx];
check_bnf_warnings(rule, rule_idx + 1);
}


for (const string &rule : rules) {
smatch match;
if (regex_match(rule, match, terminal_pattern)) {
string name = match[1].str();
string pattern = match[2].str();

int id = get_or_create_symbol_id(name);
if ((int)terminal_patterns.size() <= id) {
terminal_patterns.resize(id + 1);
}
terminal_patterns[id] = pattern;
terminal_order.push_back(id);
terminals.insert(id);
}
}


for (const string &rule : rules) {
smatch match;
if (regex_match(rule, match, production_pattern)) {
string lhs = match[1].str();
string rhs_all = match[2].str();

int lhs_id = get_or_create_symbol_id(lhs);
nonterminals.insert(lhs_id);

if (lhs == "START") {
start_symbol_id = lhs_id;
}

istringstream rhs_stream(rhs_all);
string rhs_part;
while (getline(rhs_stream, rhs_part, '|')) {
rhs_part.erase(0, rhs_part.find_first_not_of(" \t"));
rhs_part.erase(rhs_part.find_last_not_of(" \t") + 1);

if (!rhs_part.empty()) {
vector<int> rhs_ids;
istringstream symbol_stream(rhs_part);
string symbol;
while (symbol_stream >> symbol) {
int symbol_id = get_or_create_symbol_id(symbol);
rhs_ids.push_back(symbol_id);
}
productions.emplace_back(lhs_id, rhs_ids);


check_production_warnings(lhs, rhs_part, productions.size());
}
}
}
}
}

private:

void check_bnf_warnings(const string &rule, int rule_number) {

int equals_count = 0;
int define_equals_count = 0;
bool in_escape = false;

for (size_t i = 0; i < rule.length(); i++) {
char c = rule[i];

if (in_escape) {
in_escape = false;
continue;
}

if (c == '\\') {
in_escape = true;
continue;
}


if (i + 2 < rule.length() && rule.substr(i, 3) == "::=") {
define_equals_count++;
i += 2; 
} 

else if (c == '=' && (i == 0 || rule[i-1] != ':') && (i + 1 >= rule.length() || rule[i+1] != '=')) {
equals_count++;
}
}
}


void check_production_warnings(const string &lhs, const string &rhs, int production_number) {

istringstream symbol_stream(rhs);
string symbol;
vector<string> symbols_without_hash;

while (symbol_stream >> symbol) {
if (!symbol.empty() && symbol[0] != '#') {

symbols_without_hash.push_back(symbol);
}
}
}


bool contains_unescaped_hash(const string &text) {
bool in_escape = false;

for (size_t i = 0; i < text.length(); i++) {
char c = text[i];

if (in_escape) {
in_escape = false;
continue;
}

if (c == '\\') {
in_escape = true;
continue;
}

if (c == '#') {
return true;
}
}

return false;
}


void compute_first_sets() {

for (int term_id : terminals) {
first_sets[term_id].insert(term_id);
}


for (int nonterm_id : nonterminals) {
first_sets[nonterm_id] = hash_set<int>();
}

bool changed = true;
while (changed) {
changed = false;

for (const auto &prod : productions) {
int lhs = prod.lhs;
const auto &rhs = prod.rhs;

hash_set<int> first_rhs = compute_first_of_sequence(rhs);

for (int sym : first_rhs) {
if (first_sets[lhs].find(sym) == first_sets[lhs].end()) {
first_sets[lhs].insert(sym);
changed = true;
}
}
}
}
}


hash_set<int> compute_first_of_sequence(const vector<int> &sequence) {
hash_set<int> result;

if (sequence.empty()) {
result.insert(-1); 
return result;
}

for (int i = 0; i < (int)sequence.size(); i++) {
int symbol_id = sequence[i];
int resolved_id = resolve_symbol_reference(symbol_id);

if (is_terminal_symbol(symbol_id)) {
result.insert(resolved_id);
break;
} else if (is_nonterminal_symbol(symbol_id)) {
bool has_epsilon = false;
for (int sym : first_sets[resolved_id]) {
if (sym == -1) {
has_epsilon = true;
} else {
result.insert(sym);
}
}

if (!has_epsilon) {
break;
}

if (i == (int)sequence.size() - 1) {
result.insert(-1); 
}
}
}

return result;
}


void compute_follow_sets() {
int eof_id = get_or_create_symbol_id("$");
follow_sets[start_symbol_id].insert(eof_id);

bool changed = true;
while (changed) {
changed = false;

for (const auto &prod : productions) {
for (int i = 0; i < (int)prod.rhs.size(); i++) {
int symbol_id = prod.rhs[i];
int resolved_id = resolve_symbol_reference(symbol_id);

if (is_nonterminal_symbol(symbol_id)) {
vector<int> beta(prod.rhs.begin() + i + 1, prod.rhs.end());
hash_set<int> first_beta = compute_first_of_sequence(beta);

for (int sym : first_beta) {
if (sym != -1 && follow_sets[resolved_id].find(sym) == follow_sets[resolved_id].end()) {
follow_sets[resolved_id].insert(sym);
changed = true;
}
}

if (first_beta.find(-1) != first_beta.end()) {
for (int sym : follow_sets[prod.lhs]) {
if (follow_sets[resolved_id].find(sym) == follow_sets[resolved_id].end()) {
follow_sets[resolved_id].insert(sym);
changed = true;
}
}
}
}
}
}
}
}


hash_set<LRItem, LRItemHash> closure(const hash_set<LRItem, LRItemHash> &items) {
hash_set<LRItem, LRItemHash> result = items;
bool changed = true;

while (changed) {
changed = false;
vector<LRItem> new_items;

for (const auto &item : result) {
int next_sym = item.next_symbol();
if (next_sym != -1 && is_nonterminal_symbol(next_sym)) {
int resolved_id = resolve_symbol_reference(next_sym);

for (int prod_idx = 0; prod_idx < (int)productions.size(); prod_idx++) {
const auto &prod = productions[prod_idx];
if (prod.lhs == resolved_id) {
LRItem new_item(prod.lhs, prod.rhs, 0);
if (result.find(new_item) == result.end()) {
bool found = false;
for (const auto &ni : new_items) {
if (ni == new_item) {
found = true;
break;
}
}
if (!found) {
new_items.push_back(new_item);
changed = true;
}
}
}
}
}
}

for (const auto &item : new_items) {
result.insert(item);
}
}

return result;
}


hash_set<LRItem, LRItemHash> goto_func(const hash_set<LRItem, LRItemHash> &items, int symbol_id) {
hash_set<LRItem, LRItemHash> goto_items;

for (const auto &item : items) {
if (item.next_symbol() == symbol_id) {
LRItem new_item(item.lhs, item.rhs, item.dot_pos + 1);
goto_items.insert(new_item);
}
}

if (goto_items.empty()) {
return goto_items;
}

return closure(goto_items);
}


bool states_equal(const hash_set<LRItem, LRItemHash> &a, const hash_set<LRItem, LRItemHash> &b) const {
if (a.size() != b.size()) return false;
for (const auto &item : a) {
if (b.find(item) == b.end()) return false;
}
return true;
}


int find_state_id(const hash_set<LRItem, LRItemHash> &target_state) const {
for (int i = 0; i < (int)states.size(); i++) {
if (states_equal(states[i], target_state)) {
return i;
}
}
return -1;
}


void build_slr1_states() {
if (start_symbol_id == -1) {
throw runtime_error("Start symbol 'START' not found in grammar");
}

compute_first_sets();
compute_follow_sets();

augmented_start_id = get_or_create_symbol_id("_START");
productions.insert(productions.begin(), Production(augmented_start_id, {start_symbol_id}));
nonterminals.insert(augmented_start_id);


hash_set<LRItem, LRItemHash> initial_items;
LRItem initial_item(augmented_start_id, {start_symbol_id}, 0);
initial_items.insert(initial_item);

hash_set<LRItem, LRItemHash> initial_state = closure(initial_items);
states.push_back(initial_state);

queue<int> worklist;
worklist.push(0);

while (!worklist.empty()) {
int current_state_id = worklist.front();
worklist.pop();
auto current_state = states[current_state_id];

hash_set<int> symbols;
for (const auto &item : current_state) {
int next_sym = item.next_symbol();
if (next_sym != -1) {
symbols.insert(next_sym);
}
}

for (int symbol_id : symbols) {
auto next_state = goto_func(current_state, symbol_id);
if (next_state.empty()) continue;

int next_state_id = find_state_id(next_state);
if (next_state_id == -1) {
next_state_id = (int)states.size();
states.push_back(next_state);
worklist.push(next_state_id);
}

if (is_terminal_symbol(symbol_id)) {
int resolved_id = resolve_symbol_reference(symbol_id);
action_table[{current_state_id, resolved_id}] = Action(ActionType::SHIFT, next_state_id);
} else if (is_nonterminal_symbol(symbol_id)) {
int resolved_id = resolve_symbol_reference(symbol_id);
goto_table[{current_state_id, resolved_id}] = next_state_id;
}
}
}


for (int state_id = 0; state_id < (int)states.size(); state_id++) {
for (const auto &item : states[state_id]) {
if (item.is_complete()) {
if (item.lhs == augmented_start_id) {
int eof_id = get_or_create_symbol_id("$");
action_table[{state_id, eof_id}] = Action(ActionType::ACCEPT, 0);
} else {
int prod_id = find_production_id(item.lhs, item.rhs);
if (prod_id != -1) {

for (int follow_sym : follow_sets[item.lhs]) {
pair<int, int> key = {state_id, follow_sym};
auto existing = action_table.find(key);

action_table[key] = Action(ActionType::REDUCE, prod_id);
}
}
}
}
}
}
}

int find_production_id(int lhs, const vector<int> &rhs) {
for (int i = 0; i < (int)productions.size(); i++) {
if (productions[i].lhs == lhs && productions[i].rhs == rhs) {
return i;
}
}
return -1;
}


struct Token {
int type_id;
string value;
Token(int t, const string &v) : type_id(t), value(v) {}
};

enum class TokenizeResult {
SUCCESS,
INVALID_REGEX,
UNRECOGNIZED_CHARACTER
};


TokenizeResult tokenize(const string &input, vector<Token> &tokens) {
tokens.clear();
tokens.reserve(input.length() / 4);

 
struct LiteralPattern {
int type_id;
string literal;
int original_order;

LiteralPattern(int id, string lit, int order) 
: type_id(id), literal(std::move(lit)), original_order(order) {}
};

vector<LiteralPattern> patterns;
patterns.reserve(terminal_order.size() * 10);  

for (size_t order = 0; order < terminal_order.size(); order++) {
int term_id = terminal_order[order];
if (terminals.find(term_id) != terminals.end() && term_id < (int)terminal_patterns.size()) {
const string& pattern = terminal_patterns[term_id];

 
vector<string> expanded = expand_pattern(pattern);

for (const string& literal : expanded) {
patterns.emplace_back(term_id, literal, order);
}
}
}

const char* current_ptr = input.c_str();
const char* end_ptr = current_ptr + input.length();

while (current_ptr < end_ptr) {
 
while (current_ptr < end_ptr && isspace(*current_ptr)) {
++current_ptr;
}

if (current_ptr >= end_ptr) break;

bool matched = false;
size_t remaining_length = end_ptr - current_ptr;

 
for (const auto& pattern_info : patterns) {
size_t literal_len = pattern_info.literal.length();

if (remaining_length >= literal_len && 
memcmp(current_ptr, pattern_info.literal.c_str(), literal_len) == 0) {

tokens.emplace_back(pattern_info.type_id, string(current_ptr, literal_len));
current_ptr += literal_len;
matched = true;
break;
}
}

if (!matched) {
return TokenizeResult::UNRECOGNIZED_CHARACTER;
}
}

return TokenizeResult::SUCCESS;
}

private:
 
vector<string> expand_pattern(const string& pattern) const {
vector<string> result;

 
vector<string> alternatives = split_alternatives(pattern);

for (const string& alt : alternatives) {
 
if (is_character_range(alt)) {
vector<string> expanded = expand_character_range(alt);
result.insert(result.end(), expanded.begin(), expanded.end());
} else {
 
result.push_back(unescape_literal(alt));
}
}

return result;
}

 
vector<string> split_alternatives(const string& pattern) const {
vector<string> result;
size_t start = 0;
size_t pos = 0;

while (pos < pattern.length()) {
if (pattern[pos] == '|') {
if (pos > start) {
result.push_back(pattern.substr(start, pos - start));
}
start = pos + 1;
}
pos++;
}

if (start < pattern.length()) {
result.push_back(pattern.substr(start));
}

return result;
}

 
bool is_character_range(const string& str) const {
if (str.length() < 5) return false;  
if (str[0] != '[' || str[str.length()-1] != ']') return false;

string inner = str.substr(1, str.length()-2);
if (inner.length() != 3) return false;  
if (inner[1] != '-') return false;

char start_char = inner[0];
char end_char = inner[2];

return (start_char <= end_char) && 
   ((start_char >= 'a' && end_char <= 'z') || 
(start_char >= 'A' && end_char <= 'Z') ||
(start_char >= '0' && end_char <= '9'));
}

 
vector<string> expand_character_range(const string& range) const {
vector<string> result;

string inner = range.substr(1, range.length()-2);
char start_char = inner[0];
char end_char = inner[2];

for (char c = start_char; c <= end_char; c++) {
result.push_back(string(1, c));
}

return result;
}

 
string unescape_literal(const string& pattern) const {
string result;
result.reserve(pattern.length());

bool escaped = false;
for (char c : pattern) {
if (escaped) {
result += c;
escaped = false;
} else if (c == '\\') {
escaped = true;
} else {
result += c;
}
}

return result;
}

public:
parser(const string &bnf_text, bool debug = false) : debug_mode(debug) {
parse_bnf(bnf_text);
build_slr1_states();
}

node* parse(const string &input) {
vector<Token> tokens;
TokenizeResult tokenize_result = tokenize(input, tokens);

if (tokenize_result != TokenizeResult::SUCCESS) {
return nullptr;
}

int eof_id = get_or_create_symbol_id("$");
tokens.emplace_back(eof_id, "$");

vector<int> state_stack = {0};
vector<node*> symbol_stack;
int token_pos = 0;

while (true) {
if (state_stack.empty() || token_pos >= (int)tokens.size()) {
return nullptr;
}

int current_state = state_stack.back();
int current_token_type = tokens[token_pos].type_id;
string current_token_value = tokens[token_pos].value;

auto action_key = make_pair(current_state, current_token_type);
auto action_it = action_table.find(action_key);

if (action_it == action_table.end()) {
return nullptr;
}

Action action = action_it->second;

if (action.type == ActionType::SHIFT) {
state_stack.push_back(action.value);
node* new_node = new node(current_token_type, current_token_value, this);
symbol_stack.push_back(new_node);
token_pos++;
} else if (action.type == ActionType::REDUCE) {
if (action.value < 0 || action.value >= (int)productions.size()) {
return nullptr;
}

Production &prod = productions[action.value];
node* new_node = new node(prod.lhs, this);

int pop_count = (int)prod.rhs.size();
if (pop_count > (int)symbol_stack.size() || pop_count > (int)state_stack.size()) {
return nullptr;
}

for (int i = 0; i < pop_count; i++) {
node* child = symbol_stack.back();
new_node->values.insert(new_node->values.begin(), child);
symbol_stack.pop_back();
state_stack.pop_back();
}

for (auto child : new_node->values) {
if (child) {
child->set_parser(this);
}
}

symbol_stack.push_back(new_node);

if (state_stack.empty()) {
return nullptr;
}

auto goto_key = make_pair(state_stack.back(), prod.lhs);
auto goto_it = goto_table.find(goto_key);
if (goto_it == goto_table.end()) {
return nullptr;
}

state_stack.push_back(goto_it->second);
} else if (action.type == ActionType::ACCEPT) {
if (symbol_stack.empty()) {
return nullptr;
}
node* result = symbol_stack.back();
if (result) {
result->set_parser(this);
}
return result;
} else {
return nullptr;
}
}
}

string get_symbol_name(int symbol_id) const {
if (symbol_id < 0 || symbol_id >= (int)id_to_name.size()) return "";
return id_to_name[symbol_id];
}
};


string node::get_token_name() const {
if (!parser_ptr) return "";
return parser_ptr->get_symbol_name(symbol_id);
}

using ll = long long;
map<string, pair<ll, map<ll, ll>>> env;
ll eval(node* root){
if (root == nullptr) return -1;

string symbol_name = root->get_token_name();

if (symbol_name == "START"){
return eval(root->values[0]);
}

if (symbol_name == "DECL"){
string id = root->values[0]->value;
ll num = eval(root->values[2]);
env[id] = {num, {}};
return 0;
}

if (symbol_name == "ASSIGN"){
string id1 = root->values[0]->value;
ll num1 = eval(root->values[2]);
ll num2 = eval(root->values[5]);

if (env[id1].first <= num1) return -1;
if (num1 == -1 || num2 == -1) return -1;
env[id1].second[num1] = num2;
return 0;
}

if (symbol_name == "EXPR"){
if (root->values.size() == 1) {
return eval(root->values[0]);
}
else {
string id = root->values[0]->value;
ll num = eval(root->values[2]);
if (env.find(id) == env.end()) return -1;
if (env[id].second.count(num) == 0) return -1;
if (num == -1) return -1;
return env[id].second[num];
}
}

if (symbol_name == "NUM"){
if (root->values.size() == 1) {
return stoll(root->values[0]->value);
}
else {
return eval(root->values[0]) * 10 + stoll(root->values[1]->value);
}
}

return -1;
}

int main() {

bool debug = false;

auto parser0 = parser(
"ID = [A-Z]|[a-z];"
"DIGIT = [0-9];"
"NUM ::= #NUM #DIGIT | #DIGIT;"
"LPAR = \\[;"
"RPAR = \\];"
"EQ = \\=;"
"START ::= #ASSIGN;"
"ASSIGN ::= #ID #LPAR #EXPR #RPAR #EQ #EXPR;"
"EXPR ::= #NUM | #ID #LPAR #EXPR #RPAR;",
debug
);

auto parser1 = parser(
"ID = [A-Z]|[a-z];"
"DIGIT = [0-9];"
"NUM ::= #NUM #DIGIT | #DIGIT;"
"LPAR = \\[;"
"RPAR = \\];"
"START ::= #DECL;"
"DECL ::= #ID #LPAR #NUM #RPAR;",
debug
);

while (1){
int t = 1;
bool f = 0;
env.clear();

while(1){
string s;
cin >> s;
if (s == "."){
if (t == 1) return 0;
if (!f) cout << 0 << endl;
break;
}
if (f) continue;

if (s.find('=') == -1){
auto result = parser1.parse(s);
assert(result != nullptr);
eval(result);
}
else {
auto result = parser0.parse(s);
assert(result != nullptr);
if (eval(result) == -1){
cout << t << endl;
f = 1;
}
}

t++;
}
}

return 0;
}
accuracy: 1
time_ms: 50
memory_kb: 26244
final_rank: 17

code_snippet: #include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/tag_and_trait.hpp>
using namespace std;
using namespace __gnu_pbds;


struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
    
    size_t operator()(int x) const {
        return splitmix64(x);
    }
    
    size_t operator()(const string& x) const {
        uint64_t hash = 0;
        for (char c : x) {
            hash = hash * 31 + c;
        }
        return splitmix64(hash);
    }
    
    size_t operator()(const pair<int, int>& p) const {
        return splitmix64(((uint64_t)p.first << 32) | (uint64_t)p.second);
    }
};


template<typename T, typename S, typename Hash = custom_hash>
using hash_table = gp_hash_table<T, S, Hash>;
template<typename T, typename Hash = custom_hash>
using hash_set = gp_hash_table<T, null_type, Hash>;


class parser;


struct node {
    int symbol_id;
    string value;
    vector<node*> values;
    
private:
    const parser* parser_ptr;
    
public:
    node(int s, const parser* p = nullptr) : symbol_id(s), value(""), parser_ptr(p) {}
    node(int s, const string &v, const parser* p = nullptr) : symbol_id(s), value(v), parser_ptr(p) {}
    
    
    void set_parser(const parser* p) {
        parser_ptr = p;
        
        for (auto child : values) {
            if (child) {
                child->set_parser(p);
            }
        }
    }
    
    
    string get_token_name() const;
    
    
    void add_child(node* child) {
        if (child && parser_ptr) {
            child->set_parser(parser_ptr);
        }
        values.push_back(child);
    }
};


struct LRItem {
    int lhs;
    vector<int> rhs;
    int dot_pos;
    
    LRItem(int l, const vector<int> &r, int d) : lhs(l), rhs(r), dot_pos(d) {}
    
    bool operator==(const LRItem &other) const {
        return lhs == other.lhs && rhs == other.rhs && dot_pos == other.dot_pos;
    }
    
    int next_symbol() const {
        if (dot_pos < (int)rhs.size()) return rhs[dot_pos];
        return -1;
    }
    
    bool is_complete() const {
        return dot_pos >= (int)rhs.size();
    }
};


struct LRItemHash {
    size_t operator()(const LRItem &item) const {
        size_t h1 = custom_hash{}(item.lhs);
        size_t h2 = 0;
        for (int s : item.rhs) {
            h2 ^= custom_hash{}(s) + 0x9e3779b9 + (h2 << 6) + (h2 >> 2);
        }
        size_t h3 = custom_hash{}(item.dot_pos);
        return h1 ^ (h2 << 1) ^ (h3 << 2);
    }
};


enum class ActionType { SHIFT, REDUCE, ACCEPT, ERROR };

struct Action {
    ActionType type;
    int value;
    
    Action() : type(ActionType::ERROR), value(-1) {}
    Action(ActionType t, int v) : type(t), value(v) {}
    
    string to_string() const {
        switch (type) {
            case ActionType::SHIFT: return "SHIFT " + std::to_string(value);
            case ActionType::REDUCE: return "REDUCE " + std::to_string(value);
            case ActionType::ACCEPT: return "ACCEPT";
            case ActionType::ERROR: return "ERROR";
        }
        return "UNKNOWN";
    }
};


struct Production {
    int lhs;
    vector<int> rhs;
    
    Production(int l, const vector<int> &r) : lhs(l), rhs(r) {}
};

class parser {
private:
    
    vector<string> id_to_name;
    hash_table<string, int> name_to_id;
    
    
    vector<string> terminal_patterns;
    vector<int> terminal_order;
    hash_set<int> terminals;
    hash_set<int> nonterminals;
    vector<Production> productions;
    
    
    hash_table<int, hash_set<int>> first_sets;
    hash_table<int, hash_set<int>> follow_sets;
    
    
    vector<hash_set<LRItem, LRItemHash>> states;
    hash_table<pair<int, int>, Action> action_table;
    hash_table<pair<int, int>, int> goto_table;
    
    int start_symbol_id = -1;
    int augmented_start_id = -1;
    bool debug_mode = false;
    
    
    int get_or_create_symbol_id(const string &name) {
        auto it = name_to_id.find(name);
        if (it != name_to_id.end()) {
            return it->second;
        }
        int id = (int)id_to_name.size();
        id_to_name.push_back(name);
        name_to_id[name] = id;
        return id;
    }
    
    int get_or_create_symbol_id_const(const string &name) const {
        auto it = name_to_id.find(name);
        if (it != name_to_id.end()) {
            return it->second;
        }
        return -1;
    }
    
    
    int resolve_symbol_reference(int symbol_id) const {
        if (symbol_id == -1 || symbol_id >= (int)id_to_name.size()) return symbol_id;
        const string &name = id_to_name[symbol_id];
        if (name.length() > 0 && name[0] == '#') {
            string actual_name = name.substr(1);
            auto it = name_to_id.find(actual_name);
            if (it != name_to_id.end()) {
                return it->second;
            }
        }
        return symbol_id;
    }
    
    bool is_terminal_symbol(int symbol_id) const {
        int resolved_id = resolve_symbol_reference(symbol_id);
        if (resolved_id == -1) return false;
        return terminals.find(resolved_id) != terminals.end() && 
               nonterminals.find(resolved_id) == nonterminals.end();
    }
    
    bool is_nonterminal_symbol(int symbol_id) const {
        int resolved_id = resolve_symbol_reference(symbol_id);
        if (resolved_id == -1) return false;
        return nonterminals.find(resolved_id) != nonterminals.end();
    }
    
    
    string production_to_string(const Production &prod) const {
        string result = get_symbol_name(prod.lhs) + " ::= ";
        for (int symbol_id : prod.rhs) {
            int resolved_id = resolve_symbol_reference(symbol_id);
            result += get_symbol_name(resolved_id) + " ";
        }
        return result;
    }
    
    
    vector<string> split_by_semicolon(const string &text) {
        vector<string> rules;
        stringstream ss(text);
        string rule;
        
        while (getline(ss, rule, ';')) {
            rule.erase(0, rule.find_first_not_of(" \t\r\n"));
            rule.erase(rule.find_last_not_of(" \t\r\n") + 1);
            
            if (!rule.empty()) {
                rules.push_back(rule);
            }
        }
        
        return rules;
    }
    
    
    
void parse_bnf(const string &bnf_text) {
    regex terminal_pattern(R"(^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*?)\s*$)");
    regex production_pattern(R"(^\s*([A-Za-z_][A-Za-z0-9_]*)\s*::=\s*(.*?)\s*$)");
    
    vector<string> rules = split_by_semicolon(bnf_text);
    
    
    for (size_t rule_idx = 0; rule_idx < rules.size(); rule_idx++) {
        const string &rule = rules[rule_idx];
        check_bnf_warnings(rule, rule_idx + 1);
    }
    
    
    for (const string &rule : rules) {
        smatch match;
        if (regex_match(rule, match, terminal_pattern)) {
            string name = match[1].str();
            string pattern = match[2].str();
            
            int id = get_or_create_symbol_id(name);
            if ((int)terminal_patterns.size() <= id) {
                terminal_patterns.resize(id + 1);
            }
            terminal_patterns[id] = pattern;
            terminal_order.push_back(id);
            terminals.insert(id);
        }
    }
    
    
    for (const string &rule : rules) {
        smatch match;
        if (regex_match(rule, match, production_pattern)) {
            string lhs = match[1].str();
            string rhs_all = match[2].str();
            
            int lhs_id = get_or_create_symbol_id(lhs);
            nonterminals.insert(lhs_id);
            
            if (lhs == "START") {
                start_symbol_id = lhs_id;
            }
            
            istringstream rhs_stream(rhs_all);
            string rhs_part;
            while (getline(rhs_stream, rhs_part, '|')) {
                rhs_part.erase(0, rhs_part.find_first_not_of(" \t"));
                rhs_part.erase(rhs_part.find_last_not_of(" \t") + 1);
                
                if (!rhs_part.empty()) {
                    vector<int> rhs_ids;
                    istringstream symbol_stream(rhs_part);
                    string symbol;
                    while (symbol_stream >> symbol) {
                        int symbol_id = get_or_create_symbol_id(symbol);
                        rhs_ids.push_back(symbol_id);
                    }
                    productions.emplace_back(lhs_id, rhs_ids);
                    
                    
                    check_production_warnings(lhs, rhs_part, productions.size());
                }
            }
        }
    }
}

private:
    
    void check_bnf_warnings(const string &rule, int rule_number) {
        
        int equals_count = 0;
        int define_equals_count = 0;
        bool in_escape = false;
        
        for (size_t i = 0; i < rule.length(); i++) {
            char c = rule[i];
            
            if (in_escape) {
                in_escape = false;
                continue;
            }
            
            if (c == '\\') {
                in_escape = true;
                continue;
            }
            
            
            if (i + 2 < rule.length() && rule.substr(i, 3) == "::=") {
                define_equals_count++;
                i += 2; 
            } 
            
            else if (c == '=' && (i == 0 || rule[i-1] != ':') && (i + 1 >= rule.length() || rule[i+1] != '=')) {
                equals_count++;
            }
        }
        
        int total_equals = equals_count + define_equals_count;
    }
    
    
    void check_production_warnings(const string &lhs, const string &rhs, int production_number) {
        
        istringstream symbol_stream(rhs);
        string symbol;
        vector<string> symbols_without_hash;
        
        while (symbol_stream >> symbol) {
            if (!symbol.empty() && symbol[0] != '#') {
                
                symbols_without_hash.push_back(symbol);
            }
        }
    }
    
    
    bool contains_unescaped_hash(const string &text) {
        bool in_escape = false;
        
        for (size_t i = 0; i < text.length(); i++) {
            char c = text[i];
            
            if (in_escape) {
                in_escape = false;
                continue;
            }
            
            if (c == '\\') {
                in_escape = true;
                continue;
            }
            
            if (c == '#') {
                return true;
            }
        }
        
        return false;
    }
    
    
    void compute_first_sets() {
        
        for (int term_id : terminals) {
            first_sets[term_id].insert(term_id);
        }
        
        
        for (int nonterm_id : nonterminals) {
            first_sets[nonterm_id] = hash_set<int>();
        }
        
        bool changed = true;
        while (changed) {
            changed = false;
            
            for (const auto &prod : productions) {
                int lhs = prod.lhs;
                const auto &rhs = prod.rhs;
                
                hash_set<int> first_rhs = compute_first_of_sequence(rhs);
                
                for (int sym : first_rhs) {
                    if (first_sets[lhs].find(sym) == first_sets[lhs].end()) {
                        first_sets[lhs].insert(sym);
                        changed = true;
                    }
                }
            }
        }
    }
    
    
    hash_set<int> compute_first_of_sequence(const vector<int> &sequence) {
        hash_set<int> result;
        
        if (sequence.empty()) {
            result.insert(-1); 
            return result;
        }
        
        for (int i = 0; i < (int)sequence.size(); i++) {
            int symbol_id = sequence[i];
            int resolved_id = resolve_symbol_reference(symbol_id);
            
            if (is_terminal_symbol(symbol_id)) {
                result.insert(resolved_id);
                break;
            } else if (is_nonterminal_symbol(symbol_id)) {
                bool has_epsilon = false;
                for (int sym : first_sets[resolved_id]) {
                    if (sym == -1) {
                        has_epsilon = true;
                    } else {
                        result.insert(sym);
                    }
                }
                
                if (!has_epsilon) {
                    break;
                }
                
                if (i == (int)sequence.size() - 1) {
                    result.insert(-1); 
                }
            }
        }
        
        return result;
    }
    
    
    void compute_follow_sets() {
        int eof_id = get_or_create_symbol_id("$");
        follow_sets[start_symbol_id].insert(eof_id);
        
        bool changed = true;
        while (changed) {
            changed = false;
            
            for (const auto &prod : productions) {
                for (int i = 0; i < (int)prod.rhs.size(); i++) {
                    int symbol_id = prod.rhs[i];
                    int resolved_id = resolve_symbol_reference(symbol_id);
                    
                    if (is_nonterminal_symbol(symbol_id)) {
                        vector<int> beta(prod.rhs.begin() + i + 1, prod.rhs.end());
                        hash_set<int> first_beta = compute_first_of_sequence(beta);
                        
                        for (int sym : first_beta) {
                            if (sym != -1 && follow_sets[resolved_id].find(sym) == follow_sets[resolved_id].end()) {
                                follow_sets[resolved_id].insert(sym);
                                changed = true;
                            }
                        }
                        
                        if (first_beta.find(-1) != first_beta.end()) {
                            for (int sym : follow_sets[prod.lhs]) {
                                if (follow_sets[resolved_id].find(sym) == follow_sets[resolved_id].end()) {
                                    follow_sets[resolved_id].insert(sym);
                                    changed = true;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    
    hash_set<LRItem, LRItemHash> closure(const hash_set<LRItem, LRItemHash> &items) {
        hash_set<LRItem, LRItemHash> result = items;
        bool changed = true;
        
        while (changed) {
            changed = false;
            vector<LRItem> new_items;
            
            for (const auto &item : result) {
                int next_sym = item.next_symbol();
                if (next_sym != -1 && is_nonterminal_symbol(next_sym)) {
                    int resolved_id = resolve_symbol_reference(next_sym);
                    
                    for (int prod_idx = 0; prod_idx < (int)productions.size(); prod_idx++) {
                        const auto &prod = productions[prod_idx];
                        if (prod.lhs == resolved_id) {
                            LRItem new_item(prod.lhs, prod.rhs, 0);
                            if (result.find(new_item) == result.end()) {
                                bool found = false;
                                for (const auto &ni : new_items) {
                                    if (ni == new_item) {
                                        found = true;
                                        break;
                                    }
                                }
                                if (!found) {
                                    new_items.push_back(new_item);
                                    changed = true;
                                }
                            }
                        }
                    }
                }
            }
            
            for (const auto &item : new_items) {
                result.insert(item);
            }
        }
        
        return result;
    }
    
    
    hash_set<LRItem, LRItemHash> goto_func(const hash_set<LRItem, LRItemHash> &items, int symbol_id) {
        hash_set<LRItem, LRItemHash> goto_items;
        
        for (const auto &item : items) {
            if (item.next_symbol() == symbol_id) {
                LRItem new_item(item.lhs, item.rhs, item.dot_pos + 1);
                goto_items.insert(new_item);
            }
        }
        
        if (goto_items.empty()) {
            return goto_items;
        }
        
        return closure(goto_items);
    }
    
    
    bool states_equal(const hash_set<LRItem, LRItemHash> &a, const hash_set<LRItem, LRItemHash> &b) const {
        if (a.size() != b.size()) return false;
        for (const auto &item : a) {
            if (b.find(item) == b.end()) return false;
        }
        return true;
    }
    
    
    int find_state_id(const hash_set<LRItem, LRItemHash> &target_state) const {
        for (int i = 0; i < (int)states.size(); i++) {
            if (states_equal(states[i], target_state)) {
                return i;
            }
        }
        return -1;
    }
    
    
    void build_slr1_states() {
        if (start_symbol_id == -1) {
            throw runtime_error("Start symbol 'START' not found in grammar");
        }
        
        compute_first_sets();
        compute_follow_sets();
        
        augmented_start_id = get_or_create_symbol_id("_START");
        productions.insert(productions.begin(), Production(augmented_start_id, {start_symbol_id}));
        nonterminals.insert(augmented_start_id);
        
        
        hash_set<LRItem, LRItemHash> initial_items;
        LRItem initial_item(augmented_start_id, {start_symbol_id}, 0);
        initial_items.insert(initial_item);
        
        hash_set<LRItem, LRItemHash> initial_state = closure(initial_items);
        states.push_back(initial_state);
        
        queue<int> worklist;
        worklist.push(0);
        
        while (!worklist.empty()) {
            int current_state_id = worklist.front();
            worklist.pop();
            auto current_state = states[current_state_id];
            
            hash_set<int> symbols;
            for (const auto &item : current_state) {
                int next_sym = item.next_symbol();
                if (next_sym != -1) {
                    symbols.insert(next_sym);
                }
            }
            
            for (int symbol_id : symbols) {
                auto next_state = goto_func(current_state, symbol_id);
                if (next_state.empty()) continue;
                
                int next_state_id = find_state_id(next_state);
                if (next_state_id == -1) {
                    next_state_id = (int)states.size();
                    states.push_back(next_state);
                    worklist.push(next_state_id);
                }
                
                if (is_terminal_symbol(symbol_id)) {
                    int resolved_id = resolve_symbol_reference(symbol_id);
                    action_table[{current_state_id, resolved_id}] = Action(ActionType::SHIFT, next_state_id);
                } else if (is_nonterminal_symbol(symbol_id)) {
                    int resolved_id = resolve_symbol_reference(symbol_id);
                    goto_table[{current_state_id, resolved_id}] = next_state_id;
                }
            }
        }
        
        
        for (int state_id = 0; state_id < (int)states.size(); state_id++) {
            for (const auto &item : states[state_id]) {
                if (item.is_complete()) {
                    if (item.lhs == augmented_start_id) {
                        int eof_id = get_or_create_symbol_id("$");
                        action_table[{state_id, eof_id}] = Action(ActionType::ACCEPT, 0);
                    } else {
                        int prod_id = find_production_id(item.lhs, item.rhs);
                        if (prod_id != -1) {
                            
                            for (int follow_sym : follow_sets[item.lhs]) {
                                pair<int, int> key = {state_id, follow_sym};
                                auto existing = action_table.find(key);
                                
                                action_table[key] = Action(ActionType::REDUCE, prod_id);
                            }
                        }
                    }
                }
            }
        }
    }
    
    int find_production_id(int lhs, const vector<int> &rhs) {
        for (int i = 0; i < (int)productions.size(); i++) {
            if (productions[i].lhs == lhs && productions[i].rhs == rhs) {
                return i;
            }
        }
        return -1;
    }
    
    
    struct Token {
        int type_id;
        string value;
        Token(int t, const string &v) : type_id(t), value(v) {}
    };
    
    enum class TokenizeResult {
        SUCCESS,
        INVALID_REGEX,
        UNRECOGNIZED_CHARACTER
    };
    
    
TokenizeResult tokenize(const string &input, vector<Token> &tokens) {
    tokens.clear();
    vector<regex> patterns;
    vector<int> type_ids;
    
    for (int term_id : terminal_order) {
        if (terminals.find(term_id) != terminals.end() && term_id < (int)terminal_patterns.size()) {
            try {
                patterns.push_back(regex(terminal_patterns[term_id]));
                type_ids.push_back(term_id);
            } catch (const regex_error &e) {
                return TokenizeResult::INVALID_REGEX;
            }
        }
    }
    
    auto start = input.cbegin();
    while (start != input.cend()) {
        if (isspace(*start)) {
            ++start;
            continue;
        }
        
        
        int best_match_length = 0;
        int best_match_type = -1;
        string best_match_value = "";
        
        for (size_t i = 0; i < patterns.size(); i++) {
            smatch match;
            if (regex_search(start, input.cend(), match, patterns[i]) && match.position() == 0) {
                int match_length = (int)match.length();
                
                
                if (match_length > best_match_length || 
                    (match_length == best_match_length && best_match_type == -1)) {
                    best_match_length = match_length;
                    best_match_type = type_ids[i];
                    best_match_value = match.str();
                }
            }
        }
        
        if (best_match_type == -1) {
            return TokenizeResult::UNRECOGNIZED_CHARACTER;
        }
        
        tokens.emplace_back(best_match_type, best_match_value);
        start += best_match_length;
    }
    
    return TokenizeResult::SUCCESS;
}
    
public:
    parser(const string &bnf_text, bool debug = false) : debug_mode(debug) {
        parse_bnf(bnf_text);
        build_slr1_states();
    }
    
    node* parse(const string &input) {
        vector<Token> tokens;
        TokenizeResult tokenize_result = tokenize(input, tokens);
        
        if (tokenize_result != TokenizeResult::SUCCESS) {
            return nullptr;
        }
        
        int eof_id = get_or_create_symbol_id("$");
        tokens.emplace_back(eof_id, "$");
        
        vector<int> state_stack = {0};
        vector<node*> symbol_stack;
        int token_pos = 0;
        
        while (true) {
            if (state_stack.empty() || token_pos >= (int)tokens.size()) {
                return nullptr;
            }
            
            int current_state = state_stack.back();
            int current_token_type = tokens[token_pos].type_id;
            string current_token_value = tokens[token_pos].value;
            
            auto action_key = make_pair(current_state, current_token_type);
            auto action_it = action_table.find(action_key);
            
            if (action_it == action_table.end()) {
                return nullptr;
            }
            
            Action action = action_it->second;
            
            if (action.type == ActionType::SHIFT) {
                state_stack.push_back(action.value);
                node* new_node = new node(current_token_type, current_token_value, this);
                symbol_stack.push_back(new_node);
                token_pos++;
            } else if (action.type == ActionType::REDUCE) {
                if (action.value < 0 || action.value >= (int)productions.size()) {
                    return nullptr;
                }
                
                Production &prod = productions[action.value];
                node* new_node = new node(prod.lhs, this);
                
                int pop_count = (int)prod.rhs.size();
                if (pop_count > (int)symbol_stack.size() || pop_count > (int)state_stack.size()) {
                    return nullptr;
                }
                
                for (int i = 0; i < pop_count; i++) {
                    node* child = symbol_stack.back();
                    new_node->values.insert(new_node->values.begin(), child);
                    symbol_stack.pop_back();
                    state_stack.pop_back();
                }
                
                for (auto child : new_node->values) {
                    if (child) {
                        child->set_parser(this);
                    }
                }
                
                symbol_stack.push_back(new_node);
                
                if (state_stack.empty()) {
                    return nullptr;
                }
                
                auto goto_key = make_pair(state_stack.back(), prod.lhs);
                auto goto_it = goto_table.find(goto_key);
                if (goto_it == goto_table.end()) {
                    return nullptr;
                }
                
                state_stack.push_back(goto_it->second);
            } else if (action.type == ActionType::ACCEPT) {
                if (symbol_stack.empty()) {
                    return nullptr;
                }
                node* result = symbol_stack.back();
                if (result) {
                    result->set_parser(this);
                }
                return result;
            } else {
                return nullptr;
            }
        }
    }
    
    string get_symbol_name(int symbol_id) const {
        if (symbol_id < 0 || symbol_id >= (int)id_to_name.size()) return "";
        return id_to_name[symbol_id];
    }
};


string node::get_token_name() const {
    if (!parser_ptr) return "";
    return parser_ptr->get_symbol_name(symbol_id);
}

using ll = long long;
map<string, pair<ll, map<ll, ll>>> env;
ll eval(node* root){
    if (root == nullptr) return -1;
    
    string symbol_name = root->get_token_name();
    
    if (symbol_name == "START"){
        return eval(root->values[0]);
    }

    if (symbol_name == "DECL"){
        string id = root->values[0]->value;
        ll num = stoll(root->values[2]->value);
        env[id] = {num, {}};
        return 0;
    }

    if (symbol_name == "ASSIGN"){
        string id1 = root->values[0]->value;
        ll num1 = eval(root->values[2]);
        ll num2 = eval(root->values[5]);

        if (env[id1].first <= num1) return -1;
        if (num1 == -1 || num2 == -1) return -1;
        env[id1].second[num1] = num2;
        return 0;
    }

    if (symbol_name == "EXPR"){
        if (root->values.size() == 1) {
            return stoll(root->values[0]->value);
        }
        else {
            string id = root->values[0]->value;
            ll num = eval(root->values[2]);
            if (env.find(id) == env.end()) return -1;
            if (env[id].second.count(num) == 0) return -1;
            if (num == -1) return -1;
            return env[id].second[num];
        }
    }

    if (symbol_name == "NUM") return stoll(root->value);
    
    return -1;
}

int main() {
    
    bool debug = false;
    
    auto parser0 = parser(
        "ID = [A-Z]|[a-z];"
        "NUM = 0|([1-9][0-9]*);"
        "LPAR = \\[;"
        "RPAR = \\];"
        "EQ = \\=;"
        "START ::= #ASSIGN;"
        "ASSIGN ::= #ID #LPAR #EXPR #RPAR #EQ #EXPR;"
        "EXPR ::= #NUM | #ID #LPAR #EXPR #RPAR;",
        debug
    );
    
    auto parser1 = parser(
        "ID = [A-Z]|[a-z];"
        "NUM = 0|([1-9][0-9]*);"
        "LPAR = \\[;"
        "RPAR = \\];"
        "START ::= #DECL;"
        "DECL ::= #ID #LPAR #NUM #RPAR;",
        debug
    );
    
    while (1){
        int t = 1;
        bool f = 0;
        env.clear();

        while(1){
            string s;
            cin >> s;
            if (s == "."){
                if (t == 1) return 0;
                if (!f) cout << 0 << '\n';
                break;
            }
            if (f) continue;
            
            if (s.find('=') == -1){
                auto result = parser1.parse(s);
                assert(result != nullptr);
                eval(result);
            }
            else {
                auto result = parser0.parse(s);
                assert(result != nullptr);
                if (eval(result) == -1){
                    cout << t << '\n';
                    f = 1;
                }
            }

            t++;
        }
    }
    
    return 0;
}
accuracy: 1
time_ms: 550
memory_kb: 19916
final_rank: 18

code_snippet: #include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/tag_and_trait.hpp>
using namespace std;
using namespace __gnu_pbds;


struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
    
    size_t operator()(int x) const {
        return splitmix64(x);
    }

    size_t operator()(long long x) const {
        return splitmix64(static_cast<uint64_t>(x));
    }
    
    size_t operator()(const string& x) const {
        uint64_t hash = 0;
        for (char c : x) {
            hash = hash * 31 + c;
        }
        return splitmix64(hash);
    }
    
    size_t operator()(const pair<int, int>& p) const {
        return splitmix64(((uint64_t)p.first << 32) | (uint64_t)p.second);
    }
};


template<typename T, typename S, typename Hash = custom_hash>
using hash_table = gp_hash_table<T, S, Hash>;
template<typename T, typename Hash = custom_hash>
using hash_set = gp_hash_table<T, null_type, Hash>;


class parser;


struct node {
    int symbol_id;
    string value;
    vector<node*> values;
    
private:
    const parser* parser_ptr;
    
public:
    node(int s, const parser* p = nullptr) : symbol_id(s), value(""), parser_ptr(p) {}
    node(int s, const string &v, const parser* p = nullptr) : symbol_id(s), value(v), parser_ptr(p) {}
    
    
    void set_parser(const parser* p) {
        parser_ptr = p;
        
        for (auto child : values) {
            if (child) {
                child->set_parser(p);
            }
        }
    }
    
    
    string get_token_name() const;
    
    
    void add_child(node* child) {
        if (child && parser_ptr) {
            child->set_parser(parser_ptr);
        }
        values.push_back(child);
    }
};


struct LRItem {
    int lhs;
    vector<int> rhs;
    int dot_pos;
    
    LRItem(int l, const vector<int> &r, int d) : lhs(l), rhs(r), dot_pos(d) {}
    
    bool operator==(const LRItem &other) const {
        return lhs == other.lhs && rhs == other.rhs && dot_pos == other.dot_pos;
    }
    
    int next_symbol() const {
        if (dot_pos < (int)rhs.size()) return rhs[dot_pos];
        return -1;
    }
    
    bool is_complete() const {
        return dot_pos >= (int)rhs.size();
    }
};


struct LRItemHash {
    size_t operator()(const LRItem &item) const {
        size_t h1 = custom_hash{}(item.lhs);
        size_t h2 = 0;
        for (int s : item.rhs) {
            h2 ^= custom_hash{}(s) + 0x9e3779b9 + (h2 << 6) + (h2 >> 2);
        }
        size_t h3 = custom_hash{}(item.dot_pos);
        return h1 ^ (h2 << 1) ^ (h3 << 2);
    }
};


enum class ActionType { SHIFT, REDUCE, ACCEPT, ERROR };

struct Action {
    ActionType type;
    int value;
    
    Action() : type(ActionType::ERROR), value(-1) {}
    Action(ActionType t, int v) : type(t), value(v) {}
    
    string to_string() const {
        switch (type) {
            case ActionType::SHIFT: return "SHIFT " + std::to_string(value);
            case ActionType::REDUCE: return "REDUCE " + std::to_string(value);
            case ActionType::ACCEPT: return "ACCEPT";
            case ActionType::ERROR: return "ERROR";
        }
        return "UNKNOWN";
    }
};


struct Production {
    int lhs;
    vector<int> rhs;
    
    Production(int l, const vector<int> &r) : lhs(l), rhs(r) {}
};

class parser {
private:
    
    vector<string> id_to_name;
    hash_table<string, int> name_to_id;
    
    
    vector<string> terminal_patterns;
    vector<int> terminal_order;
    hash_set<int> terminals;
    hash_set<int> nonterminals;
    vector<Production> productions;
    
    
    hash_table<int, hash_set<int>> first_sets;
    hash_table<int, hash_set<int>> follow_sets;
    
    
    vector<hash_set<LRItem, LRItemHash>> states;
    hash_table<pair<int, int>, Action> action_table;
    hash_table<pair<int, int>, int> goto_table;
    
    int start_symbol_id = -1;
    int augmented_start_id = -1;
    bool debug_mode = false;
    
    
    int get_or_create_symbol_id(const string &name) {
        auto it = name_to_id.find(name);
        if (it != name_to_id.end()) {
            return it->second;
        }
        int id = (int)id_to_name.size();
        id_to_name.push_back(name);
        name_to_id[name] = id;
        return id;
    }
    
    int get_or_create_symbol_id_const(const string &name) const {
        auto it = name_to_id.find(name);
        if (it != name_to_id.end()) {
            return it->second;
        }
        return -1;
    }
    
    
    int resolve_symbol_reference(int symbol_id) const {
        if (symbol_id == -1 || symbol_id >= (int)id_to_name.size()) return symbol_id;
        const string &name = id_to_name[symbol_id];
        if (name.length() > 0 && name[0] == '#') {
            string actual_name = name.substr(1);
            auto it = name_to_id.find(actual_name);
            if (it != name_to_id.end()) {
                return it->second;
            }
        }
        return symbol_id;
    }
    
    bool is_terminal_symbol(int symbol_id) const {
        int resolved_id = resolve_symbol_reference(symbol_id);
        if (resolved_id == -1) return false;
        return terminals.find(resolved_id) != terminals.end() && 
               nonterminals.find(resolved_id) == nonterminals.end();
    }
    
    bool is_nonterminal_symbol(int symbol_id) const {
        int resolved_id = resolve_symbol_reference(symbol_id);
        if (resolved_id == -1) return false;
        return nonterminals.find(resolved_id) != nonterminals.end();
    }
    
    
    string production_to_string(const Production &prod) const {
        string result = get_symbol_name(prod.lhs) + " ::= ";
        for (int symbol_id : prod.rhs) {
            int resolved_id = resolve_symbol_reference(symbol_id);
            result += get_symbol_name(resolved_id) + " ";
        }
        return result;
    }
    
    
    vector<string> split_by_semicolon(const string &text) {
        vector<string> rules;
        stringstream ss(text);
        string rule;
        
        while (getline(ss, rule, ';')) {
            rule.erase(0, rule.find_first_not_of(" \t\r\n"));
            rule.erase(rule.find_last_not_of(" \t\r\n") + 1);
            
            if (!rule.empty()) {
                rules.push_back(rule);
            }
        }
        
        return rules;
    }
    
    
    
void parse_bnf(const string &bnf_text) {
    regex terminal_pattern(R"(^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*?)\s*$)");
    regex production_pattern(R"(^\s*([A-Za-z_][A-Za-z0-9_]*)\s*::=\s*(.*?)\s*$)");
    
    vector<string> rules = split_by_semicolon(bnf_text);
    
    
    for (size_t rule_idx = 0; rule_idx < rules.size(); rule_idx++) {
        const string &rule = rules[rule_idx];
        check_bnf_warnings(rule, rule_idx + 1);
    }
    
    
    for (const string &rule : rules) {
        smatch match;
        if (regex_match(rule, match, terminal_pattern)) {
            string name = match[1].str();
            string pattern = match[2].str();
            
            int id = get_or_create_symbol_id(name);
            if ((int)terminal_patterns.size() <= id) {
                terminal_patterns.resize(id + 1);
            }
            terminal_patterns[id] = pattern;
            terminal_order.push_back(id);
            terminals.insert(id);
        }
    }
    
    
    for (const string &rule : rules) {
        smatch match;
        if (regex_match(rule, match, production_pattern)) {
            string lhs = match[1].str();
            string rhs_all = match[2].str();
            
            int lhs_id = get_or_create_symbol_id(lhs);
            nonterminals.insert(lhs_id);
            
            if (lhs == "START") {
                start_symbol_id = lhs_id;
            }
            
            istringstream rhs_stream(rhs_all);
            string rhs_part;
            while (getline(rhs_stream, rhs_part, '|')) {
                rhs_part.erase(0, rhs_part.find_first_not_of(" \t"));
                rhs_part.erase(rhs_part.find_last_not_of(" \t") + 1);
                
                if (!rhs_part.empty()) {
                    vector<int> rhs_ids;
                    istringstream symbol_stream(rhs_part);
                    string symbol;
                    while (symbol_stream >> symbol) {
                        int symbol_id = get_or_create_symbol_id(symbol);
                        rhs_ids.push_back(symbol_id);
                    }
                    productions.emplace_back(lhs_id, rhs_ids);
                    
                    
                    check_production_warnings(lhs, rhs_part, productions.size());
                }
            }
        }
    }
}

private:
    
    void check_bnf_warnings(const string &rule, int rule_number) {
        
        int equals_count = 0;
        int define_equals_count = 0;
        bool in_escape = false;
        
        for (size_t i = 0; i < rule.length(); i++) {
            char c = rule[i];
            
            if (in_escape) {
                in_escape = false;
                continue;
            }
            
            if (c == '\\') {
                in_escape = true;
                continue;
            }
            
            
            if (i + 2 < rule.length() && rule.substr(i, 3) == "::=") {
                define_equals_count++;
                i += 2; 
            } 
            
            else if (c == '=' && (i == 0 || rule[i-1] != ':') && (i + 1 >= rule.length() || rule[i+1] != '=')) {
                equals_count++;
            }
        }
        
        int total_equals = equals_count + define_equals_count;
    }
    
    
    void check_production_warnings(const string &lhs, const string &rhs, int production_number) {
        
        istringstream symbol_stream(rhs);
        string symbol;
        vector<string> symbols_without_hash;
        
        while (symbol_stream >> symbol) {
            if (!symbol.empty() && symbol[0] != '#') {
                
                symbols_without_hash.push_back(symbol);
            }
        }
    }
    
    
    bool contains_unescaped_hash(const string &text) {
        bool in_escape = false;
        
        for (size_t i = 0; i < text.length(); i++) {
            char c = text[i];
            
            if (in_escape) {
                in_escape = false;
                continue;
            }
            
            if (c == '\\') {
                in_escape = true;
                continue;
            }
            
            if (c == '#') {
                return true;
            }
        }
        
        return false;
    }
    
    
    void compute_first_sets() {
        
        for (int term_id : terminals) {
            first_sets[term_id].insert(term_id);
        }
        
        
        for (int nonterm_id : nonterminals) {
            first_sets[nonterm_id] = hash_set<int>();
        }
        
        bool changed = true;
        while (changed) {
            changed = false;
            
            for (const auto &prod : productions) {
                int lhs = prod.lhs;
                const auto &rhs = prod.rhs;
                
                hash_set<int> first_rhs = compute_first_of_sequence(rhs);
                
                for (int sym : first_rhs) {
                    if (first_sets[lhs].find(sym) == first_sets[lhs].end()) {
                        first_sets[lhs].insert(sym);
                        changed = true;
                    }
                }
            }
        }
    }
    
    
    hash_set<int> compute_first_of_sequence(const vector<int> &sequence) {
        hash_set<int> result;
        
        if (sequence.empty()) {
            result.insert(-1); 
            return result;
        }
        
        for (int i = 0; i < (int)sequence.size(); i++) {
            int symbol_id = sequence[i];
            int resolved_id = resolve_symbol_reference(symbol_id);
            
            if (is_terminal_symbol(symbol_id)) {
                result.insert(resolved_id);
                break;
            } else if (is_nonterminal_symbol(symbol_id)) {
                bool has_epsilon = false;
                for (int sym : first_sets[resolved_id]) {
                    if (sym == -1) {
                        has_epsilon = true;
                    } else {
                        result.insert(sym);
                    }
                }
                
                if (!has_epsilon) {
                    break;
                }
                
                if (i == (int)sequence.size() - 1) {
                    result.insert(-1); 
                }
            }
        }
        
        return result;
    }
    
    
    void compute_follow_sets() {
        int eof_id = get_or_create_symbol_id("$");
        follow_sets[start_symbol_id].insert(eof_id);
        
        bool changed = true;
        while (changed) {
            changed = false;
            
            for (const auto &prod : productions) {
                for (int i = 0; i < (int)prod.rhs.size(); i++) {
                    int symbol_id = prod.rhs[i];
                    int resolved_id = resolve_symbol_reference(symbol_id);
                    
                    if (is_nonterminal_symbol(symbol_id)) {
                        vector<int> beta(prod.rhs.begin() + i + 1, prod.rhs.end());
                        hash_set<int> first_beta = compute_first_of_sequence(beta);
                        
                        for (int sym : first_beta) {
                            if (sym != -1 && follow_sets[resolved_id].find(sym) == follow_sets[resolved_id].end()) {
                                follow_sets[resolved_id].insert(sym);
                                changed = true;
                            }
                        }
                        
                        if (first_beta.find(-1) != first_beta.end()) {
                            for (int sym : follow_sets[prod.lhs]) {
                                if (follow_sets[resolved_id].find(sym) == follow_sets[resolved_id].end()) {
                                    follow_sets[resolved_id].insert(sym);
                                    changed = true;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    
    hash_set<LRItem, LRItemHash> closure(const hash_set<LRItem, LRItemHash> &items) {
        hash_set<LRItem, LRItemHash> result = items;
        bool changed = true;
        
        while (changed) {
            changed = false;
            vector<LRItem> new_items;
            
            for (const auto &item : result) {
                int next_sym = item.next_symbol();
                if (next_sym != -1 && is_nonterminal_symbol(next_sym)) {
                    int resolved_id = resolve_symbol_reference(next_sym);
                    
                    for (int prod_idx = 0; prod_idx < (int)productions.size(); prod_idx++) {
                        const auto &prod = productions[prod_idx];
                        if (prod.lhs == resolved_id) {
                            LRItem new_item(prod.lhs, prod.rhs, 0);
                            if (result.find(new_item) == result.end()) {
                                bool found = false;
                                for (const auto &ni : new_items) {
                                    if (ni == new_item) {
                                        found = true;
                                        break;
                                    }
                                }
                                if (!found) {
                                    new_items.push_back(new_item);
                                    changed = true;
                                }
                            }
                        }
                    }
                }
            }
            
            for (const auto &item : new_items) {
                result.insert(item);
            }
        }
        
        return result;
    }
    
    
    hash_set<LRItem, LRItemHash> goto_func(const hash_set<LRItem, LRItemHash> &items, int symbol_id) {
        hash_set<LRItem, LRItemHash> goto_items;
        
        for (const auto &item : items) {
            if (item.next_symbol() == symbol_id) {
                LRItem new_item(item.lhs, item.rhs, item.dot_pos + 1);
                goto_items.insert(new_item);
            }
        }
        
        if (goto_items.empty()) {
            return goto_items;
        }
        
        return closure(goto_items);
    }
    
    
    bool states_equal(const hash_set<LRItem, LRItemHash> &a, const hash_set<LRItem, LRItemHash> &b) const {
        if (a.size() != b.size()) return false;
        for (const auto &item : a) {
            if (b.find(item) == b.end()) return false;
        }
        return true;
    }
    
    
    int find_state_id(const hash_set<LRItem, LRItemHash> &target_state) const {
        for (int i = 0; i < (int)states.size(); i++) {
            if (states_equal(states[i], target_state)) {
                return i;
            }
        }
        return -1;
    }
    
    
    void build_slr1_states() {
        if (start_symbol_id == -1) {
            throw runtime_error("Start symbol 'START' not found in grammar");
        }
        
        compute_first_sets();
        compute_follow_sets();
        
        augmented_start_id = get_or_create_symbol_id("_START");
        productions.insert(productions.begin(), Production(augmented_start_id, {start_symbol_id}));
        nonterminals.insert(augmented_start_id);
        
        
        hash_set<LRItem, LRItemHash> initial_items;
        LRItem initial_item(augmented_start_id, {start_symbol_id}, 0);
        initial_items.insert(initial_item);
        
        hash_set<LRItem, LRItemHash> initial_state = closure(initial_items);
        states.push_back(initial_state);
        
        queue<int> worklist;
        worklist.push(0);
        
        while (!worklist.empty()) {
            int current_state_id = worklist.front();
            worklist.pop();
            auto current_state = states[current_state_id];
            
            hash_set<int> symbols;
            for (const auto &item : current_state) {
                int next_sym = item.next_symbol();
                if (next_sym != -1) {
                    symbols.insert(next_sym);
                }
            }
            
            for (int symbol_id : symbols) {
                auto next_state = goto_func(current_state, symbol_id);
                if (next_state.empty()) continue;
                
                int next_state_id = find_state_id(next_state);
                if (next_state_id == -1) {
                    next_state_id = (int)states.size();
                    states.push_back(next_state);
                    worklist.push(next_state_id);
                }
                
                if (is_terminal_symbol(symbol_id)) {
                    int resolved_id = resolve_symbol_reference(symbol_id);
                    action_table[{current_state_id, resolved_id}] = Action(ActionType::SHIFT, next_state_id);
                } else if (is_nonterminal_symbol(symbol_id)) {
                    int resolved_id = resolve_symbol_reference(symbol_id);
                    goto_table[{current_state_id, resolved_id}] = next_state_id;
                }
            }
        }
        
        
        for (int state_id = 0; state_id < (int)states.size(); state_id++) {
            for (const auto &item : states[state_id]) {
                if (item.is_complete()) {
                    if (item.lhs == augmented_start_id) {
                        int eof_id = get_or_create_symbol_id("$");
                        action_table[{state_id, eof_id}] = Action(ActionType::ACCEPT, 0);
                    } else {
                        int prod_id = find_production_id(item.lhs, item.rhs);
                        if (prod_id != -1) {
                            
                            for (int follow_sym : follow_sets[item.lhs]) {
                                pair<int, int> key = {state_id, follow_sym};
                                auto existing = action_table.find(key);
                                
                                action_table[key] = Action(ActionType::REDUCE, prod_id);
                            }
                        }
                    }
                }
            }
        }
    }
    
    int find_production_id(int lhs, const vector<int> &rhs) {
        for (int i = 0; i < (int)productions.size(); i++) {
            if (productions[i].lhs == lhs && productions[i].rhs == rhs) {
                return i;
            }
        }
        return -1;
    }
    
    
    struct Token {
        int type_id;
        string value;
        Token(int t, const string &v) : type_id(t), value(v) {}
    };
    
    enum class TokenizeResult {
        SUCCESS,
        INVALID_REGEX,
        UNRECOGNIZED_CHARACTER
    };
    
    
TokenizeResult tokenize(const string &input, vector<Token> &tokens) {
    tokens.clear();
    vector<regex> patterns;
    vector<int> type_ids;
    
    for (int term_id : terminal_order) {
        if (terminals.find(term_id) != terminals.end() && term_id < (int)terminal_patterns.size()) {
            try {
                patterns.push_back(regex(terminal_patterns[term_id]));
                type_ids.push_back(term_id);
            } catch (const regex_error &e) {
                return TokenizeResult::INVALID_REGEX;
            }
        }
    }
    
    auto start = input.cbegin();
    while (start != input.cend()) {
        if (isspace(*start)) {
            ++start;
            continue;
        }
        
        
        int best_match_length = 0;
        int best_match_type = -1;
        string best_match_value = "";
        
        for (size_t i = 0; i < patterns.size(); i++) {
            smatch match;
            if (regex_search(start, input.cend(), match, patterns[i]) && match.position() == 0) {
                int match_length = (int)match.length();
                
                
                if (match_length > best_match_length || 
                    (match_length == best_match_length && best_match_type == -1)) {
                    best_match_length = match_length;
                    best_match_type = type_ids[i];
                    best_match_value = match.str();
                }
            }
        }
        
        if (best_match_type == -1) {
            return TokenizeResult::UNRECOGNIZED_CHARACTER;
        }
        
        tokens.emplace_back(best_match_type, best_match_value);
        start += best_match_length;
    }
    
    return TokenizeResult::SUCCESS;
}
    
public:
    parser(const string &bnf_text, bool debug = false) : debug_mode(debug) {
        parse_bnf(bnf_text);
        build_slr1_states();
    }
    
    node* parse(const string &input) {
        vector<Token> tokens;
        TokenizeResult tokenize_result = tokenize(input, tokens);
        
        if (tokenize_result != TokenizeResult::SUCCESS) {
            return nullptr;
        }
        
        int eof_id = get_or_create_symbol_id("$");
        tokens.emplace_back(eof_id, "$");
        
        vector<int> state_stack = {0};
        vector<node*> symbol_stack;
        int token_pos = 0;
        
        while (true) {
            if (state_stack.empty() || token_pos >= (int)tokens.size()) {
                return nullptr;
            }
            
            int current_state = state_stack.back();
            int current_token_type = tokens[token_pos].type_id;
            string current_token_value = tokens[token_pos].value;
            
            auto action_key = make_pair(current_state, current_token_type);
            auto action_it = action_table.find(action_key);
            
            if (action_it == action_table.end()) {
                return nullptr;
            }
            
            Action action = action_it->second;
            
            if (action.type == ActionType::SHIFT) {
                state_stack.push_back(action.value);
                node* new_node = new node(current_token_type, current_token_value, this);
                symbol_stack.push_back(new_node);
                token_pos++;
            } else if (action.type == ActionType::REDUCE) {
                if (action.value < 0 || action.value >= (int)productions.size()) {
                    return nullptr;
                }
                
                Production &prod = productions[action.value];
                node* new_node = new node(prod.lhs, this);
                
                int pop_count = (int)prod.rhs.size();
                if (pop_count > (int)symbol_stack.size() || pop_count > (int)state_stack.size()) {
                    return nullptr;
                }
                
                for (int i = 0; i < pop_count; i++) {
                    node* child = symbol_stack.back();
                    new_node->values.insert(new_node->values.begin(), child);
                    symbol_stack.pop_back();
                    state_stack.pop_back();
                }
                
                for (auto child : new_node->values) {
                    if (child) {
                        child->set_parser(this);
                    }
                }
                
                symbol_stack.push_back(new_node);
                
                if (state_stack.empty()) {
                    return nullptr;
                }
                
                auto goto_key = make_pair(state_stack.back(), prod.lhs);
                auto goto_it = goto_table.find(goto_key);
                if (goto_it == goto_table.end()) {
                    return nullptr;
                }
                
                state_stack.push_back(goto_it->second);
            } else if (action.type == ActionType::ACCEPT) {
                if (symbol_stack.empty()) {
                    return nullptr;
                }
                node* result = symbol_stack.back();
                if (result) {
                    result->set_parser(this);
                }
                return result;
            } else {
                return nullptr;
            }
        }
    }
    
    string get_symbol_name(int symbol_id) const {
        if (symbol_id < 0 || symbol_id >= (int)id_to_name.size()) return "";
        return id_to_name[symbol_id];
    }
};


string node::get_token_name() const {
    if (!parser_ptr) return "";
    return parser_ptr->get_symbol_name(symbol_id);
}

using ll = long long;
hash_table<string, pair<ll, hash_table<ll, ll>>> env;
ll eval(node* root){
    if (root == nullptr) return -1;
    
    string symbol_name = root->get_token_name();
    
    if (symbol_name == "START"){
        return eval(root->values[0]);
    }

    if (symbol_name == "DECL"){
        string id = root->values[0]->value;
        ll num = stoll(root->values[2]->value);
        env[id] = {num, {}};
        return 0;
    }

    if (symbol_name == "ASSIGN"){
        string id1 = root->values[0]->value;
        ll num1 = eval(root->values[2]);
        ll num2 = eval(root->values[5]);

        if (env[id1].first <= num1) return -1;
        if (num1 == -1 || num2 == -1) return -1;
        env[id1].second[num1] = num2;
        return 0;
    }

    if (symbol_name == "EXPR"){
        if (root->values.size() == 1) {
            return stoll(root->values[0]->value);
        }
        else {
            string id = root->values[0]->value;
            ll num = eval(root->values[2]);
            if (env.find(id) == env.end()) return -1;
            if (env[id].second.find(num) == env[id].second.end()) return -1;
            if (num == -1) return -1;
            return env[id].second[num];
        }
    }

    if (symbol_name == "NUM") return stoll(root->value);
    
    return -1;
}

int main() {
    
    bool debug = false;
    
    auto parser0 = parser(
        "ID = [A-Z]|[a-z];"
        "NUM = 0|([1-9][0-9]*);"
        "LPAR = \\[;"
        "RPAR = \\];"
        "EQ = \\=;"
        "START ::= #ASSIGN;"
        "ASSIGN ::= #ID #LPAR #EXPR #RPAR #EQ #EXPR;"
        "EXPR ::= #NUM | #ID #LPAR #EXPR #RPAR;",
        debug
    );
    
    auto parser1 = parser(
        "ID = [A-Z]|[a-z];"
        "NUM = 0|([1-9][0-9]*);"
        "LPAR = \\[;"
        "RPAR = \\];"
        "START ::= #DECL;"
        "DECL ::= #ID #LPAR #NUM #RPAR;",
        debug
    );
    
    while (1){
        int t = 1;
        bool f = 0;
        env.clear();

        while(1){
            string s;
            cin >> s;
            if (s == "."){
                if (t == 1) return 0;
                if (!f) cout << 0 << endl;
                break;
            }
            if (f) continue;
            
            if (s.find('=') == -1){
                auto result = parser1.parse(s);
                assert(result != nullptr);
                eval(result);
            }
            else {
                auto result = parser0.parse(s);
                assert(result != nullptr);
                if (eval(result) == -1){
                    cout << t << endl;
                    f = 1;
                }
            }

            t++;
        }
    }
    
    return 0;
}
accuracy: 1
time_ms: 560
memory_kb: 20080
final_rank: 20

code_snippet: #include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/tag_and_trait.hpp>
using namespace std;
using namespace __gnu_pbds;


struct custom_hash {
    static uint64_t splitmix64(uint64_t x) {
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }

    size_t operator()(uint64_t x) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(x + FIXED_RANDOM);
    }
    
    size_t operator()(int x) const {
        return splitmix64(x);
    }
    
    size_t operator()(const string& x) const {
        uint64_t hash = 0;
        for (char c : x) {
            hash = hash * 31 + c;
        }
        return splitmix64(hash);
    }
    
    size_t operator()(const pair<int, int>& p) const {
        return splitmix64(((uint64_t)p.first << 32) | (uint64_t)p.second);
    }
};


template<typename T, typename S, typename Hash = custom_hash>
using hash_table = gp_hash_table<T, S, Hash>;
template<typename T, typename Hash = custom_hash>
using hash_set = gp_hash_table<T, null_type, Hash>;


class parser;


struct node {
    int symbol_id;
    string value;
    vector<node*> values;
    
private:
    const parser* parser_ptr;
    
public:
    node(int s, const parser* p = nullptr) : symbol_id(s), value(""), parser_ptr(p) {}
    node(int s, const string &v, const parser* p = nullptr) : symbol_id(s), value(v), parser_ptr(p) {}
    
    
    void set_parser(const parser* p) {
        parser_ptr = p;
        
        for (auto child : values) {
            if (child) {
                child->set_parser(p);
            }
        }
    }
    
    
    string get_token_name() const;
    
    
    void add_child(node* child) {
        if (child && parser_ptr) {
            child->set_parser(parser_ptr);
        }
        values.push_back(child);
    }
};


struct LRItem {
    int lhs;
    vector<int> rhs;
    int dot_pos;
    
    LRItem(int l, const vector<int> &r, int d) : lhs(l), rhs(r), dot_pos(d) {}
    
    bool operator==(const LRItem &other) const {
        return lhs == other.lhs && rhs == other.rhs && dot_pos == other.dot_pos;
    }
    
    int next_symbol() const {
        if (dot_pos < (int)rhs.size()) return rhs[dot_pos];
        return -1;
    }
    
    bool is_complete() const {
        return dot_pos >= (int)rhs.size();
    }
};


struct LRItemHash {
    size_t operator()(const LRItem &item) const {
        size_t h1 = custom_hash{}(item.lhs);
        size_t h2 = 0;
        for (int s : item.rhs) {
            h2 ^= custom_hash{}(s) + 0x9e3779b9 + (h2 << 6) + (h2 >> 2);
        }
        size_t h3 = custom_hash{}(item.dot_pos);
        return h1 ^ (h2 << 1) ^ (h3 << 2);
    }
};


enum class ActionType { SHIFT, REDUCE, ACCEPT, ERROR };

struct Action {
    ActionType type;
    int value;
    
    Action() : type(ActionType::ERROR), value(-1) {}
    Action(ActionType t, int v) : type(t), value(v) {}
    
    string to_string() const {
        switch (type) {
            case ActionType::SHIFT: return "SHIFT " + std::to_string(value);
            case ActionType::REDUCE: return "REDUCE " + std::to_string(value);
            case ActionType::ACCEPT: return "ACCEPT";
            case ActionType::ERROR: return "ERROR";
        }
        return "UNKNOWN";
    }
};


struct Production {
    int lhs;
    vector<int> rhs;
    
    Production(int l, const vector<int> &r) : lhs(l), rhs(r) {}
};

class parser {
private:
    
    vector<string> id_to_name;
    hash_table<string, int> name_to_id;
    
    
    vector<string> terminal_patterns;
    vector<int> terminal_order;
    hash_set<int> terminals;
    hash_set<int> nonterminals;
    vector<Production> productions;
    
    
    hash_table<int, hash_set<int>> first_sets;
    hash_table<int, hash_set<int>> follow_sets;
    
    
    vector<hash_set<LRItem, LRItemHash>> states;
    hash_table<pair<int, int>, Action> action_table;
    hash_table<pair<int, int>, int> goto_table;
    
    int start_symbol_id = -1;
    int augmented_start_id = -1;
    bool debug_mode = false;
    
    
    int get_or_create_symbol_id(const string &name) {
        auto it = name_to_id.find(name);
        if (it != name_to_id.end()) {
            return it->second;
        }
        int id = (int)id_to_name.size();
        id_to_name.push_back(name);
        name_to_id[name] = id;
        return id;
    }
    
    int get_or_create_symbol_id_const(const string &name) const {
        auto it = name_to_id.find(name);
        if (it != name_to_id.end()) {
            return it->second;
        }
        return -1;
    }
    
    
    int resolve_symbol_reference(int symbol_id) const {
        if (symbol_id == -1 || symbol_id >= (int)id_to_name.size()) return symbol_id;
        const string &name = id_to_name[symbol_id];
        if (name.length() > 0 && name[0] == '#') {
            string actual_name = name.substr(1);
            auto it = name_to_id.find(actual_name);
            if (it != name_to_id.end()) {
                return it->second;
            }
        }
        return symbol_id;
    }
    
    bool is_terminal_symbol(int symbol_id) const {
        int resolved_id = resolve_symbol_reference(symbol_id);
        if (resolved_id == -1) return false;
        return terminals.find(resolved_id) != terminals.end() && 
               nonterminals.find(resolved_id) == nonterminals.end();
    }
    
    bool is_nonterminal_symbol(int symbol_id) const {
        int resolved_id = resolve_symbol_reference(symbol_id);
        if (resolved_id == -1) return false;
        return nonterminals.find(resolved_id) != nonterminals.end();
    }
    
    
    string production_to_string(const Production &prod) const {
        string result = get_symbol_name(prod.lhs) + " ::= ";
        for (int symbol_id : prod.rhs) {
            int resolved_id = resolve_symbol_reference(symbol_id);
            result += get_symbol_name(resolved_id) + " ";
        }
        return result;
    }
    
    
    vector<string> split_by_semicolon(const string &text) {
        vector<string> rules;
        stringstream ss(text);
        string rule;
        
        while (getline(ss, rule, ';')) {
            rule.erase(0, rule.find_first_not_of(" \t\r\n"));
            rule.erase(rule.find_last_not_of(" \t\r\n") + 1);
            
            if (!rule.empty()) {
                rules.push_back(rule);
            }
        }
        
        return rules;
    }
    
    
    
void parse_bnf(const string &bnf_text) {
    regex terminal_pattern(R"(^\s*([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*?)\s*$)");
    regex production_pattern(R"(^\s*([A-Za-z_][A-Za-z0-9_]*)\s*::=\s*(.*?)\s*$)");
    
    vector<string> rules = split_by_semicolon(bnf_text);
    
    
    for (size_t rule_idx = 0; rule_idx < rules.size(); rule_idx++) {
        const string &rule = rules[rule_idx];
        check_bnf_warnings(rule, rule_idx + 1);
    }
    
    
    for (const string &rule : rules) {
        smatch match;
        if (regex_match(rule, match, terminal_pattern)) {
            string name = match[1].str();
            string pattern = match[2].str();
            
            int id = get_or_create_symbol_id(name);
            if ((int)terminal_patterns.size() <= id) {
                terminal_patterns.resize(id + 1);
            }
            terminal_patterns[id] = pattern;
            terminal_order.push_back(id);
            terminals.insert(id);
        }
    }
    
    
    for (const string &rule : rules) {
        smatch match;
        if (regex_match(rule, match, production_pattern)) {
            string lhs = match[1].str();
            string rhs_all = match[2].str();
            
            int lhs_id = get_or_create_symbol_id(lhs);
            nonterminals.insert(lhs_id);
            
            if (lhs == "START") {
                start_symbol_id = lhs_id;
            }
            
            istringstream rhs_stream(rhs_all);
            string rhs_part;
            while (getline(rhs_stream, rhs_part, '|')) {
                rhs_part.erase(0, rhs_part.find_first_not_of(" \t"));
                rhs_part.erase(rhs_part.find_last_not_of(" \t") + 1);
                
                if (!rhs_part.empty()) {
                    vector<int> rhs_ids;
                    istringstream symbol_stream(rhs_part);
                    string symbol;
                    while (symbol_stream >> symbol) {
                        int symbol_id = get_or_create_symbol_id(symbol);
                        rhs_ids.push_back(symbol_id);
                    }
                    productions.emplace_back(lhs_id, rhs_ids);
                    
                    
                    check_production_warnings(lhs, rhs_part, productions.size());
                }
            }
        }
    }
}

private:
    
    void check_bnf_warnings(const string &rule, int rule_number) {
        
        int equals_count = 0;
        int define_equals_count = 0;
        bool in_escape = false;
        
        for (size_t i = 0; i < rule.length(); i++) {
            char c = rule[i];
            
            if (in_escape) {
                in_escape = false;
                continue;
            }
            
            if (c == '\\') {
                in_escape = true;
                continue;
            }
            
            
            if (i + 2 < rule.length() && rule.substr(i, 3) == "::=") {
                define_equals_count++;
                i += 2; 
            } 
            
            else if (c == '=' && (i == 0 || rule[i-1] != ':') && (i + 1 >= rule.length() || rule[i+1] != '=')) {
                equals_count++;
            }
        }
        
        int total_equals = equals_count + define_equals_count;
    }
    
    
    void check_production_warnings(const string &lhs, const string &rhs, int production_number) {
        
        istringstream symbol_stream(rhs);
        string symbol;
        vector<string> symbols_without_hash;
        
        while (symbol_stream >> symbol) {
            if (!symbol.empty() && symbol[0] != '#') {
                
                symbols_without_hash.push_back(symbol);
            }
        }
    }
    
    
    bool contains_unescaped_hash(const string &text) {
        bool in_escape = false;
        
        for (size_t i = 0; i < text.length(); i++) {
            char c = text[i];
            
            if (in_escape) {
                in_escape = false;
                continue;
            }
            
            if (c == '\\') {
                in_escape = true;
                continue;
            }
            
            if (c == '#') {
                return true;
            }
        }
        
        return false;
    }
    
    
    void compute_first_sets() {
        
        for (int term_id : terminals) {
            first_sets[term_id].insert(term_id);
        }
        
        
        for (int nonterm_id : nonterminals) {
            first_sets[nonterm_id] = hash_set<int>();
        }
        
        bool changed = true;
        while (changed) {
            changed = false;
            
            for (const auto &prod : productions) {
                int lhs = prod.lhs;
                const auto &rhs = prod.rhs;
                
                hash_set<int> first_rhs = compute_first_of_sequence(rhs);
                
                for (int sym : first_rhs) {
                    if (first_sets[lhs].find(sym) == first_sets[lhs].end()) {
                        first_sets[lhs].insert(sym);
                        changed = true;
                    }
                }
            }
        }
    }
    
    
    hash_set<int> compute_first_of_sequence(const vector<int> &sequence) {
        hash_set<int> result;
        
        if (sequence.empty()) {
            result.insert(-1); 
            return result;
        }
        
        for (int i = 0; i < (int)sequence.size(); i++) {
            int symbol_id = sequence[i];
            int resolved_id = resolve_symbol_reference(symbol_id);
            
            if (is_terminal_symbol(symbol_id)) {
                result.insert(resolved_id);
                break;
            } else if (is_nonterminal_symbol(symbol_id)) {
                bool has_epsilon = false;
                for (int sym : first_sets[resolved_id]) {
                    if (sym == -1) {
                        has_epsilon = true;
                    } else {
                        result.insert(sym);
                    }
                }
                
                if (!has_epsilon) {
                    break;
                }
                
                if (i == (int)sequence.size() - 1) {
                    result.insert(-1); 
                }
            }
        }
        
        return result;
    }
    
    
    void compute_follow_sets() {
        int eof_id = get_or_create_symbol_id("$");
        follow_sets[start_symbol_id].insert(eof_id);
        
        bool changed = true;
        while (changed) {
            changed = false;
            
            for (const auto &prod : productions) {
                for (int i = 0; i < (int)prod.rhs.size(); i++) {
                    int symbol_id = prod.rhs[i];
                    int resolved_id = resolve_symbol_reference(symbol_id);
                    
                    if (is_nonterminal_symbol(symbol_id)) {
                        vector<int> beta(prod.rhs.begin() + i + 1, prod.rhs.end());
                        hash_set<int> first_beta = compute_first_of_sequence(beta);
                        
                        for (int sym : first_beta) {
                            if (sym != -1 && follow_sets[resolved_id].find(sym) == follow_sets[resolved_id].end()) {
                                follow_sets[resolved_id].insert(sym);
                                changed = true;
                            }
                        }
                        
                        if (first_beta.find(-1) != first_beta.end()) {
                            for (int sym : follow_sets[prod.lhs]) {
                                if (follow_sets[resolved_id].find(sym) == follow_sets[resolved_id].end()) {
                                    follow_sets[resolved_id].insert(sym);
                                    changed = true;
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    
    hash_set<LRItem, LRItemHash> closure(const hash_set<LRItem, LRItemHash> &items) {
        hash_set<LRItem, LRItemHash> result = items;
        bool changed = true;
        
        while (changed) {
            changed = false;
            vector<LRItem> new_items;
            
            for (const auto &item : result) {
                int next_sym = item.next_symbol();
                if (next_sym != -1 && is_nonterminal_symbol(next_sym)) {
                    int resolved_id = resolve_symbol_reference(next_sym);
                    
                    for (int prod_idx = 0; prod_idx < (int)productions.size(); prod_idx++) {
                        const auto &prod = productions[prod_idx];
                        if (prod.lhs == resolved_id) {
                            LRItem new_item(prod.lhs, prod.rhs, 0);
                            if (result.find(new_item) == result.end()) {
                                bool found = false;
                                for (const auto &ni : new_items) {
                                    if (ni == new_item) {
                                        found = true;
                                        break;
                                    }
                                }
                                if (!found) {
                                    new_items.push_back(new_item);
                                    changed = true;
                                }
                            }
                        }
                    }
                }
            }
            
            for (const auto &item : new_items) {
                result.insert(item);
            }
        }
        
        return result;
    }
    
    
    hash_set<LRItem, LRItemHash> goto_func(const hash_set<LRItem, LRItemHash> &items, int symbol_id) {
        hash_set<LRItem, LRItemHash> goto_items;
        
        for (const auto &item : items) {
            if (item.next_symbol() == symbol_id) {
                LRItem new_item(item.lhs, item.rhs, item.dot_pos + 1);
                goto_items.insert(new_item);
            }
        }
        
        if (goto_items.empty()) {
            return goto_items;
        }
        
        return closure(goto_items);
    }
    
    
    bool states_equal(const hash_set<LRItem, LRItemHash> &a, const hash_set<LRItem, LRItemHash> &b) const {
        if (a.size() != b.size()) return false;
        for (const auto &item : a) {
            if (b.find(item) == b.end()) return false;
        }
        return true;
    }
    
    
    int find_state_id(const hash_set<LRItem, LRItemHash> &target_state) const {
        for (int i = 0; i < (int)states.size(); i++) {
            if (states_equal(states[i], target_state)) {
                return i;
            }
        }
        return -1;
    }
    
    
    void build_slr1_states() {
        if (start_symbol_id == -1) {
            throw runtime_error("Start symbol 'START' not found in grammar");
        }
        
        compute_first_sets();
        compute_follow_sets();
        
        augmented_start_id = get_or_create_symbol_id("_START");
        productions.insert(productions.begin(), Production(augmented_start_id, {start_symbol_id}));
        nonterminals.insert(augmented_start_id);
        
        
        hash_set<LRItem, LRItemHash> initial_items;
        LRItem initial_item(augmented_start_id, {start_symbol_id}, 0);
        initial_items.insert(initial_item);
        
        hash_set<LRItem, LRItemHash> initial_state = closure(initial_items);
        states.push_back(initial_state);
        
        queue<int> worklist;
        worklist.push(0);
        
        while (!worklist.empty()) {
            int current_state_id = worklist.front();
            worklist.pop();
            auto current_state = states[current_state_id];
            
            hash_set<int> symbols;
            for (const auto &item : current_state) {
                int next_sym = item.next_symbol();
                if (next_sym != -1) {
                    symbols.insert(next_sym);
                }
            }
            
            for (int symbol_id : symbols) {
                auto next_state = goto_func(current_state, symbol_id);
                if (next_state.empty()) continue;
                
                int next_state_id = find_state_id(next_state);
                if (next_state_id == -1) {
                    next_state_id = (int)states.size();
                    states.push_back(next_state);
                    worklist.push(next_state_id);
                }
                
                if (is_terminal_symbol(symbol_id)) {
                    int resolved_id = resolve_symbol_reference(symbol_id);
                    action_table[{current_state_id, resolved_id}] = Action(ActionType::SHIFT, next_state_id);
                } else if (is_nonterminal_symbol(symbol_id)) {
                    int resolved_id = resolve_symbol_reference(symbol_id);
                    goto_table[{current_state_id, resolved_id}] = next_state_id;
                }
            }
        }
        
        
        for (int state_id = 0; state_id < (int)states.size(); state_id++) {
            for (const auto &item : states[state_id]) {
                if (item.is_complete()) {
                    if (item.lhs == augmented_start_id) {
                        int eof_id = get_or_create_symbol_id("$");
                        action_table[{state_id, eof_id}] = Action(ActionType::ACCEPT, 0);
                    } else {
                        int prod_id = find_production_id(item.lhs, item.rhs);
                        if (prod_id != -1) {
                            
                            for (int follow_sym : follow_sets[item.lhs]) {
                                pair<int, int> key = {state_id, follow_sym};
                                auto existing = action_table.find(key);
                                
                                action_table[key] = Action(ActionType::REDUCE, prod_id);
                            }
                        }
                    }
                }
            }
        }
    }
    
    int find_production_id(int lhs, const vector<int> &rhs) {
        for (int i = 0; i < (int)productions.size(); i++) {
            if (productions[i].lhs == lhs && productions[i].rhs == rhs) {
                return i;
            }
        }
        return -1;
    }
    
    
    struct Token {
        int type_id;
        string value;
        Token(int t, const string &v) : type_id(t), value(v) {}
    };
    
    enum class TokenizeResult {
        SUCCESS,
        INVALID_REGEX,
        UNRECOGNIZED_CHARACTER
    };
    
    
TokenizeResult tokenize(const string &input, vector<Token> &tokens) {
    tokens.clear();
    vector<regex> patterns;
    vector<int> type_ids;
    
    for (int term_id : terminal_order) {
        if (terminals.find(term_id) != terminals.end() && term_id < (int)terminal_patterns.size()) {
            try {
                patterns.push_back(regex(terminal_patterns[term_id]));
                type_ids.push_back(term_id);
            } catch (const regex_error &e) {
                return TokenizeResult::INVALID_REGEX;
            }
        }
    }
    
    auto start = input.cbegin();
    while (start != input.cend()) {
        if (isspace(*start)) {
            ++start;
            continue;
        }
        
        
        int best_match_length = 0;
        int best_match_type = -1;
        string best_match_value = "";
        
        for (size_t i = 0; i < patterns.size(); i++) {
            smatch match;
            if (regex_search(start, input.cend(), match, patterns[i]) && match.position() == 0) {
                int match_length = (int)match.length();
                
                
                if (match_length > best_match_length || 
                    (match_length == best_match_length && best_match_type == -1)) {
                    best_match_length = match_length;
                    best_match_type = type_ids[i];
                    best_match_value = match.str();
                }
            }
        }
        
        if (best_match_type == -1) {
            return TokenizeResult::UNRECOGNIZED_CHARACTER;
        }
        
        tokens.emplace_back(best_match_type, best_match_value);
        start += best_match_length;
    }
    
    return TokenizeResult::SUCCESS;
}
    
public:
    parser(const string &bnf_text, bool debug = false) : debug_mode(debug) {
        parse_bnf(bnf_text);
        build_slr1_states();
    }
    
    node* parse(const string &input) {
        vector<Token> tokens;
        TokenizeResult tokenize_result = tokenize(input, tokens);
        
        if (tokenize_result != TokenizeResult::SUCCESS) {
            return nullptr;
        }
        
        int eof_id = get_or_create_symbol_id("$");
        tokens.emplace_back(eof_id, "$");
        
        vector<int> state_stack = {0};
        vector<node*> symbol_stack;
        int token_pos = 0;
        
        while (true) {
            if (state_stack.empty() || token_pos >= (int)tokens.size()) {
                return nullptr;
            }
            
            int current_state = state_stack.back();
            int current_token_type = tokens[token_pos].type_id;
            string current_token_value = tokens[token_pos].value;
            
            auto action_key = make_pair(current_state, current_token_type);
            auto action_it = action_table.find(action_key);
            
            if (action_it == action_table.end()) {
                return nullptr;
            }
            
            Action action = action_it->second;
            
            if (action.type == ActionType::SHIFT) {
                state_stack.push_back(action.value);
                node* new_node = new node(current_token_type, current_token_value, this);
                symbol_stack.push_back(new_node);
                token_pos++;
            } else if (action.type == ActionType::REDUCE) {
                if (action.value < 0 || action.value >= (int)productions.size()) {
                    return nullptr;
                }
                
                Production &prod = productions[action.value];
                node* new_node = new node(prod.lhs, this);
                
                int pop_count = (int)prod.rhs.size();
                if (pop_count > (int)symbol_stack.size() || pop_count > (int)state_stack.size()) {
                    return nullptr;
                }
                
                for (int i = 0; i < pop_count; i++) {
                    node* child = symbol_stack.back();
                    new_node->values.insert(new_node->values.begin(), child);
                    symbol_stack.pop_back();
                    state_stack.pop_back();
                }
                
                for (auto child : new_node->values) {
                    if (child) {
                        child->set_parser(this);
                    }
                }
                
                symbol_stack.push_back(new_node);
                
                if (state_stack.empty()) {
                    return nullptr;
                }
                
                auto goto_key = make_pair(state_stack.back(), prod.lhs);
                auto goto_it = goto_table.find(goto_key);
                if (goto_it == goto_table.end()) {
                    return nullptr;
                }
                
                state_stack.push_back(goto_it->second);
            } else if (action.type == ActionType::ACCEPT) {
                if (symbol_stack.empty()) {
                    return nullptr;
                }
                node* result = symbol_stack.back();
                if (result) {
                    result->set_parser(this);
                }
                return result;
            } else {
                return nullptr;
            }
        }
    }
    
    string get_symbol_name(int symbol_id) const {
        if (symbol_id < 0 || symbol_id >= (int)id_to_name.size()) return "";
        return id_to_name[symbol_id];
    }
};


string node::get_token_name() const {
    if (!parser_ptr) return "";
    return parser_ptr->get_symbol_name(symbol_id);
}

using ll = long long;
map<string, pair<ll, map<ll, ll>>> env;
ll eval(node* root){
    if (root == nullptr) return -1;
    
    string symbol_name = root->get_token_name();
    
    if (symbol_name == "START"){
        return eval(root->values[0]);
    }

    if (symbol_name == "DECL"){
        string id = root->values[0]->value;
        ll num = stoll(root->values[2]->value);
        env[id] = {num, {}};
        return 0;
    }

    if (symbol_name == "ASSIGN"){
        string id1 = root->values[0]->value;
        ll num1 = eval(root->values[2]);
        ll num2 = eval(root->values[5]);

        if (env[id1].first <= num1) return -1;
        if (num1 == -1 || num2 == -1) return -1;
        env[id1].second[num1] = num2;
        return 0;
    }

    if (symbol_name == "EXPR"){
        if (root->values.size() == 1) {
            return stoll(root->values[0]->value);
        }
        else {
            string id = root->values[0]->value;
            ll num = eval(root->values[2]);
            if (env.find(id) == env.end()) return -1;
            if (env[id].second.count(num) == 0) return -1;
            if (num == -1) return -1;
            return env[id].second[num];
        }
    }

    if (symbol_name == "NUM") return stoll(root->value);
    
    return -1;
}

int main() {
    
    bool debug = false;
    
    auto parser0 = parser(
        "ID = [A-Z]|[a-z];"
        "NUM = 0|([1-9][0-9]*);"
        "LPAR = \\[;"
        "RPAR = \\];"
        "EQ = \\=;"
        "START ::= #ASSIGN;"
        "ASSIGN ::= #ID #LPAR #EXPR #RPAR #EQ #EXPR;"
        "EXPR ::= #NUM | #ID #LPAR #EXPR #RPAR;",
        debug
    );
    
    auto parser1 = parser(
        "ID = [A-Z]|[a-z];"
        "NUM = 0|([1-9][0-9]*);"
        "LPAR = \\[;"
        "RPAR = \\];"
        "START ::= #DECL;"
        "DECL ::= #ID #LPAR #NUM #RPAR;",
        debug
    );
    
    while (1){
        int t = 1;
        bool f = 0;
        env.clear();

        while(1){
            string s;
            cin >> s;
            if (s == "."){
                if (t == 1) return 0;
                if (!f) cout << 0 << endl;
                break;
            }
            if (f) continue;
            
            if (s.find('=') == -1){
                auto result = parser1.parse(s);
                assert(result != nullptr);
                eval(result);
            }
            else {
                auto result = parser0.parse(s);
                assert(result != nullptr);
                if (eval(result) == -1){
                    cout << t << endl;
                    f = 1;
                }
            }

            t++;
        }
    }
    
    return 0;
}
accuracy: 1
time_ms: 560
memory_kb: 20072
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;

// <expression> ::= <number> | <array_name> [ <expression> ]
// <number> ::= 0 | [1-9] [0-9]*
// <array_name> ::= [a-zA-Z]

struct Parser {
	// var
	using itr = string::const_iterator;
	itr now;
	int64_t ans;
	map<char, map<int64_t, int64_t>> arr;
	// expect
	const struct ex {
		vector<char> _012;
		vector<char> azAZ;
		ex() {
			for(char c = '0'; c <= '9'; ++c) {
				_012.push_back(c);
			}
			for(char c = 'a'; c <= 'z'; ++c) {
				azAZ.push_back(c);
			}
			for(char c = 'A'; c <= 'Z'; ++c) {
				azAZ.push_back(c);
			}
		}
	} ex;
	
	Parser(const string& s, map<char, map<int64_t, int64_t>>& arr) : arr(arr) {
		now = s.begin();
		ans = expression(now);
	}
	// <expression> ::= <number> | <array_name> [ <expression> ]
	// <array_name> ::= [a-zA-Z]
	int64_t expression(itr& now) {
		for(char c : ex.azAZ) {
			if(*now == c) {
				next(now, c);
				next(now, '[');
				int64_t ret = expression(now);
				next(now, ']');
				if(arr.count(c) and arr[c].count(ret)) {
					return arr[c][ret];
				} else {
					throw "INVALID";
				}
			}
		}
		return number(now);
	}
	// <number> ::= 0 | [1-9] [0-9]*
	int64_t number(itr& now) {
		int64_t ret = 0;
		while(true) {
			if('0' <= *now and *now <= '9') {
				ret *= 10;
				ret += (*now) - '0';
				next(now, ex._012);
			} else {
				return ret;
			}
		}
	}
	void next(itr &now, const char expected) {
		vector<char> req = {expected};
		next(now, req);
	}
	void next(itr &now, const vector<char> &expected) {
		for(char c: expected){
			if(*now == c){
				++now;
				return;
			}
		}
		// Debug
		fprintf(stderr, "Expected: ");
		for(char c: expected) {
			fprintf(stderr, "%c, ", c);
		}
		fprintf(stderr, "\nGot: %c\n", *now);
		fprintf(stderr, "Rest: ");
		while(*now) {
			fprintf(stderr, "%c", *now++);
		}
		fprintf(stderr, "\n");
		exit(1);
	}
};

void solve(string& s) {
	map<char, int64_t> sz;
	map<char, map<int64_t, int64_t>> arr;
	bool bug = false;
	for(int q = 1; ; ++q) {
		if(not bug) {
			bool dec = true;
			string s1, s2;
			for(int i = 0; i < s.size(); ++i) {
				if(s[i] == '=') {
					s1 = s.substr(0, i);
					s2 = s.substr(i + 1);
					dec = false;
					break;
				}
			}
			if(dec) {
				int64_t num = 0;
				for(int i = 2; i + 1 < s.size(); ++i) {
					num *= 10;
					num += s[i] - '0';
				}
				sz[s[0]] = num;
			} else {
				try {
					Parser p1(s1.substr(2, s1.size() - 3), arr);
					if('0' <= s2[0] and s2[0] <= '9') {
						int64_t num = 0;
						for(int i = 0; i < s2.size(); ++i) {
							num *= 10;
							num += s2[i] - '0';
						}
						if(not sz.count(s1[0])) {
							cout << q << '\n';
							bug = true;
							continue;
						}
						if(sz[s1[0]] <= p1.ans) {
							cout << q << '\n';
							bug = true;
							continue;
						}
						arr[s1[0]][p1.ans] = num;
						// cerr << s1[0] << p1.ans << " " << num << '\n';
					} else {
						Parser p2(s2, arr);
						if(not sz.count(s1[0])) {
							cout << q << '\n';
							bug = true;
							continue;
						}
						if(sz[s1[0]] <= p1.ans) {
							cout << q << '\n';
							bug = true;
							continue;
						}
						arr[s1[0]][p1.ans] = p2.ans;
						// cerr << s1[0] << p1.ans << " " << p2.ans << '\n';
					}
				} catch(...) {
					cout << q << '\n';
					bug = true;
				}
			}
		}
		cin >> s;
		if(s == ".") {
			if(not bug) {
				cout << 0 << '\n';
			}
			return;
		}
	}
}

int main() {
	string s;
	while(cin >> s and s != ".") {
		solve(s);
	}
	return 0;
}
accuracy: 1
time_ms: 40
memory_kb: 3360
final_rank: 14

code_snippet: #include <bits/stdc++.h>

using namespace std;

class Parser{
    string S;
    int pos = 0;
    public:
    bool error = false;
    map<char, map<int, int>> A;
    map<char, int> _size;
    Parser(string T) : S(T){}

    char peek(){
        return pos < S.size() ? S[pos] : 'a';
    }

    bool is_number(char c){
        return '0' <= c and c <= '9';
    }

    bool is_alphabet(char c){
        return ('a' <= c and c <= 'z') or ('A' <= c and c <= 'Z');
    }

    void skip_spaces(){
        while (peek() == ' ')
            pos++;
    }

    int64_t factor(){
        skip_spaces();
        int64_t res = 0;
        if (is_alphabet(peek())){
            char c = peek();
            pos++;
            pos++;
            res = factor();
            pos++;
            if (A.count(c) == 0){
                error = true;
                return -1;
            }
            if (_size[c] <= res){
                error = true;
                return -1;
            }
            if (A[c].count(res) == 0){
                error = true;
                return -1;
            }
            res = A[c][res];
        }
        if (is_number(peek()))
            res = number();

        skip_spaces();
        return res;
    }

    int64_t number(){
        int64_t res = 0;
        while (is_number(peek())){
            res = res * 10 + peek() - '0';
            pos++;
        }
        return res;
    }
};

vector<string> split(string S, char delim){
    vector<string> res;
    int prev = -1;
    for (int i = 0; i < S.size(); i++){
        if (S[i] == delim){
            res.push_back(S.substr(prev + 1, i - prev - 1));
            prev = i;
        }
    }
    res.push_back(S.substr(prev + 1, int(S.size()) - prev - 1));
    return res;
}

int main(){
    string prev = "";
    while (true){
        map<char, map<int, int>> A;
        map<char, int> _size;
        int ans = 0;
        int k = 1;
        while (true){
            string S;
            cin >> S;
            if (prev == "." and S == ".")
                return 0;
            prev = S;
            if (S == ".")
                break;
            if (ans != 0)
                continue;
            if (S.find('=') == string::npos){
                char c = S[0];
                Parser parser(S.substr(2));
                auto r = parser.number();
                A[c] = {};
                _size[c] = r;

            } else {
                auto sp = split(S, '=');
                auto error = false;
                if (A.count(S[0]) == 0)
                    error = true;
                auto l = sp[0];
                auto r = sp[1];
                Parser lp(l.substr(2)), rp(r);
                lp.A = A;
                rp.A = A;
                lp._size = _size;
                rp._size = _size;
                auto lres = lp.factor();
                auto rres = rp.factor();
                error |= lp.error | rp.error | _size[l[0]] <= lres;
                A[l[0]][lres] = rres;
                if (error)
                    ans = k;
            }
            k++;
        }
        cout << ans << endl;
    }
}
accuracy: 1
time_ms: 60
memory_kb: 3368
final_rank: 16

code_snippet: #include <bits/stdc++.h>
//#include <atcoder/all>
//using namespace atcoder;
const double pi = 3.141592653589793238462643383279;
using namespace std;
//typedef
//------------------------------------------
typedef vector<int> VI;
typedef vector<VI> VVI;
typedef vector<string> VS;
typedef pair<int, int> PII;
typedef pair<long long, long long> PLL;
typedef pair<int, PII> TIII;
typedef long long LL;
typedef unsigned long long ULL;
typedef vector<LL> VLL;
typedef vector<VLL> VVLL;

//container util
//------------------------------------------
#define ALL(a) (a).begin(), (a).end()
#define RALL(a) (a).rbegin(), (a).rend()
#define PB push_back
#define MP make_pair
#define SZ(a) int((a).size())
#define SQ(a) ((a) * (a))
#define EACH(i, c) for (typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define EXIST(s, e) ((s).find(e) != (s).end())
#define SORT(c) sort((c).begin(), (c).end())

//repetition
//------------------------------------------
#define FOR(i, s, n) for (int i = s; i < (int)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define MOD 1000000007

#define rep(i, a, b) for (int i = a; i < (b); ++i)
#define trav(a, x) for (auto &a : x)
#define all(x) x.begin(), x.end()
#define sz(x) (int)(x).size()

typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;

#define chmin(x, y) x = min(x, y)
#define chmax(x, y) x = max(x, y)
const double EPS = 1e-8, PI = acos(-1);
//ここから編集    
typedef string::const_iterator State;

pair<bool, pair<string, int>> compress(string s, map<string, int>& mp, map<pair<string, int>, int>& mpp){
    int m = s.size();
    stack<string> st;
    stack<int> st2;
    for(int j=0; j<m; j++){
        if(('a' <= s[j] && s[j] <= 'z') || ('A' <= s[j] && s[j] <= 'Z')){
            string tmp = "";
            int idx2 = 0;
            while(j+idx2<m && (('a' <= s[j+idx2] && s[j+idx2] <= 'z') || ('A' <= s[j+idx2] && s[j+idx2] <= 'Z'))){
                tmp += s[j+idx2];
                idx2++;
            }
            st.push(tmp);
            j += idx2-1;
        }else if('0' <= s[j] && s[j] <= '9'){
            int num = 0;
            int idx2 = 0;
            while(j+idx2<m && '0' <= s[j+idx2] && s[j+idx2] <= '9'){
                num = num*10 + s[j+idx2] - '0';
                idx2++;
            }
            st2.push(num);
            j += idx2-1;
        }
    }
    int now = st2.top();
    while(st.size()){
        if(st.size() == 1) break;
        string str = st.top();
        st.pop();
        if(mp.find(str) == mp.end()) return make_pair(false, make_pair("", -1));
        if(mpp.find(make_pair(str, now)) == mpp.end()) return make_pair(false, make_pair("", -1));
        if(mp[str] <= now) return make_pair(false, make_pair("", -1));
        now = mpp[make_pair(str, now)];
    }
    string str = st.top();
    return make_pair(true, make_pair(str, now));
}

int solve(vector<string> f){
    int n = f.size();
    map<string, int> mp;
    map<pair<string, int>, int> mpp;
    for(int i=0; i<n; i++){
        bool assign=false;
        REP(j,f[i].size()){
            if(f[i][j] == '=') assign = true;
        }
        if(assign){
            string s="", t="";
            int idx = 0;
            while(idx < f[i].size() && f[i][idx] != '='){
                s += f[i][idx];
                idx++;
            }
            idx++;
            auto p = compress(s, mp, mpp);
            if(p.first == false) return i+1;
            
            string str = p.second.first;
            if(isdigit(f[i][idx])){
                int num = 0;
                while(idx<f[i].size() && isdigit(f[i][idx])){
                    num = num * 10 + f[i][idx] - '0';
                    idx++;
                }
                if(mp.find(str) == mp.end()) return i+1;
                if(mp[str] <= p.second.second) return i+1;
                mpp[p.second] = num;
            }else{
                
                while(idx < f[i].size()){
                    t += f[i][idx];
                    idx++;
                }
                auto q = compress(t, mp, mpp);

                if(q.first == false) return i+1;
                string str2 = q.second.first;
                if(mp.find(str) == mp.end()) return i+1;
                if(mp[str] <= p.second.second) return i+1;
                if(mpp.find(q.second) == mpp.end()) return i+1;
                if(mp.find(str2) == mp.end()) return i+1;
                if(mp[str2] <= q.second.second) return i+1;
                //cout << p.second.second << " " << q.second.second << endl;
                mpp[p.second] = mpp[q.second];
            }
        }else{
            string s = "";
            int idx = 0;
            while(idx < f[i].size() && f[i][idx] != '['){
                s += f[i][idx];
                idx++;
            }
            idx++;
            int num = 0;
            while(idx < f[i].size() && isdigit(f[i][idx])){
                num = num*10 + f[i][idx]-'0';
                idx++;
            }
            mp[s] = num;
        }
    }
    return 0;
}
int main()
{
    cin.tie(0);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(6);

    string s;
    while(cin >> s){
        if(s == ".") break;

        vector<string> f;
        f.push_back(s);
        while(cin >> s){
            if(s == ".") break;
            f.push_back(s);
        }

        cout << solve(f) << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3460
final_rank: 10

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> l_l;
typedef pair<int, int> i_i;
template<class T>
inline bool chmax(T &a, T b) {
    if(a < b) {
        a = b;
        return true;
    }
    return false;
}

template<class T>
inline bool chmin(T &a, T b) {
    if(a > b) {
        a = b;
        return true;
    }
    return false;
}

const long double EPS = 1e-10;
const long long INF = 1e18;
const long double PI = acos(-1.0L);
//const ll mod = 1000000007;
vector<string> S;
map<string, map<int, int>> mp;
map<string, int> sz;
typedef pair<string, int> si;

int EqualIdx(string S) {
    for(int i = 0; i < S.size(); i++) {
        if(S[i] == '=') return i;
    }
    return -1;
}

typedef string::iterator State;

bool IsDigit(State &itr) {
    return '0' <= *itr and *itr <= '9';
}

int Number(State &itr) {
    int ret = 0;
    while(true) {
        if(!IsDigit(itr)) {
            //cerr << "Number: " << ret << endl;
            return ret;
        }
        ret = ret * 10 + (int)(*itr - '0');
        itr++;
    }
}

int val(si x) {
    //cerr << "val: " << x.first << " " << x.second << endl;
    if(x.second < 0) return x.second;
    if(x.first == ".") return x.second;
    if(sz.count(x.first) == 0) return -1;
    //cerr << "sz: " << sz[x.first] << endl;
    if(sz[x.first] <= x.second) return -1;
    if(mp[x.first].count(x.second) == 0) return -1;
    //cerr << "ok: " << endl;
    return mp[x.first][x.second];
}

si f(State &itr) {
    //cerr << "f: " << *itr << endl;
    if(IsDigit(itr)) {
        auto ret = Number(itr);
        itr++;
        return {".", ret};
    }
    string fi;
    while(*itr != '[') {
        fi.push_back(*itr);
        itr++;
    }
    itr++;
    auto Inside = f(itr);
    itr++;
    //if(Inside.first == ".") return {fi, Inside.second};
    //cerr << "Inside: " << Inside.first << " " << Inside.second << endl;
    return {fi, val(Inside)};
    //return {fi, num};
}

int main() {
    while(true) {
        S.clear();
        mp.clear();
        sz.clear();
        while(true) {
            string tmp;
            cin >> tmp;
            if(tmp == ".") break;
            S.push_back(tmp);
        }
        if(S.empty()) break;
        int ans = 0;
        for(int i = 0; i < S.size(); i++) {
            //cerr << "----" << i << "----" << endl;
            int idx = EqualIdx(S[i]);
            if(idx >= 0) {
                auto itr = S[i].begin();
                auto Left = f(itr);
                itr = S[i].begin();
                itr += idx + 1;
                auto Right = f(itr);
                if(Right.second < 0) {
                    ans = i + 1;
                    break;
                }
                //cerr << "A" << endl;
                //cerr << Right.first << " " << Right.second << endl;
                int Value = val(Right);
                //cerr << Right.first << " " << Right.second << " " << Value << endl;
                if(Value < 0) {
                    ans = i + 1;
                    break;
                }
                //cerr << "In: " << Left.first << " " << Left.second << " " << Value << endl;
                if(sz[Left.first] <= Left.second) {
                    ans = i + 1;
                    break;
                }
                mp[Left.first][Left.second] = Value;
                //cerr << Left.first << " " << Left.second << " " << Right.first << " " << Right.second << endl;
                //cerr << Left.first << " " << Left.second << " ---val--- " << Value << endl;
            } else {
                auto itr = S[i].begin();
                auto Main = f(itr);
                sz[Main.first] = Main.second;
                mp[Main.first][-2] = -1;
                //cerr << Main.first << " " << Main.second << endl;
            }
        }
        cout << ans << endl;
    }
    return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3212
final_rank: 1

code_snippet: #include<bits/stdc++.h>
#include<regex>
#include<cctype>
using namespace std;
#define INFS (1LL<<28)
#define INF (1LL<<60)
#define DEKAI 1000000007
#define MOD 998244353
#define lp(i,n) for(int i=0;i<n;i++)
#define double long double
#define all(c) begin(c), end(c)

//#define int long long 

namespace {
#define __DECLARE__(C)    \
    template <typename T> \
    std::ostream &operator<<(std::ostream &, const C<T> &);

#define __DECLAREM__(C)               \
    template <typename T, typename U> \
    std::ostream &operator<<(std::ostream &, const C<T, U> &);

__DECLARE__(std::vector)
__DECLARE__(std::deque)
__DECLARE__(std::set)
__DECLARE__(std::stack)
__DECLARE__(std::queue)
__DECLARE__(std::priority_queue)
__DECLARE__(std::unordered_set)
__DECLAREM__(std::map)
__DECLAREM__(std::unordered_map)

template <typename T, typename U>
std::ostream &operator<<(std::ostream &, const std::pair<T, U> &);
template <typename... T>
std::ostream &operator<<(std::ostream &, const std::tuple<T...> &);
template <typename T, std::size_t N>
std::ostream &operator<<(std::ostream &, const std::array<T, N> &);

template <typename Tuple, std::size_t N>
struct __TuplePrinter__ {
    static void print(std::ostream &os, const Tuple &t) {
        __TuplePrinter__<Tuple, N - 1>::print(os, t);
        os << ", " << std::get<N - 1>(t);
    }
};

template <typename Tuple>
struct __TuplePrinter__<Tuple, 1> {
    static void print(std::ostream &os, const Tuple &t) { os << std::get<0>(t); }
};

template <typename... T>
std::ostream &operator<<(std::ostream &os, const std::tuple<T...> &t) {
    os << '(';
    __TuplePrinter__<decltype(t), sizeof...(T)>::print(os, t);
    os << ')';
    return os;
}

template <typename T, typename U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &v) {
    return os << '(' << v.first << ", " << v.second << ')';
}

#define __INNER__                             \
    os << '[';                                \
    for (auto it = begin(c); it != end(c);) { \
        os << *it;                            \
        os << (++it != end(c) ? ", " : "");   \
    }                                         \
    return os << ']';

template <typename T, std::size_t N>
std::ostream &operator<<(std::ostream &os, const std::array<T, N> &c) {
    __INNER__
}

#define __DEFINE__(C)                                           \
    template <typename T>                                       \
    std::ostream &operator<<(std::ostream &os, const C<T> &c) { \
        __INNER__                                               \
    }

#define __DEFINEM__(C)                                             \
    template <typename T, typename U>                              \
    std::ostream &operator<<(std::ostream &os, const C<T, U> &c) { \
        __INNER__                                                  \
    }

#define __DEFINEW__(C, M1, M2)                                  \
    template <typename T>                                       \
    std::ostream &operator<<(std::ostream &os, const C<T> &c) { \
        std::deque<T> v;                                        \
        for (auto d = c; !d.empty(); d.pop()) v.M1(d.M2());     \
        return os << v;                                         \
    }

__DEFINE__(std::vector)
__DEFINE__(std::deque)
__DEFINE__(std::set)
__DEFINEW__(std::stack, push_front, top)
__DEFINEW__(std::queue, push_back, front)
__DEFINEW__(std::priority_queue, push_front, top)
__DEFINE__(std::unordered_set)
__DEFINEM__(std::map)
__DEFINEM__(std::unordered_map)
}


#define rep(i,n) lp(i,n)
using Weight = int;
using Flow = int;
struct Edge {
    int src, dst;
    Weight weight;
    Flow cap;
    Edge() : src(0), dst(0), weight(0) {}
    Edge(int s, int d, Weight w) : src(s), dst(d), weight(w) {}
};
using Edges = std::vector<Edge>;
using Graph = std::vector<Edges>;
using Array = std::vector<Weight>;
using Matrix = std::vector<Array>;

void add_edge(Graph &g, int a, int b, Weight w = 1) {
    g[a].emplace_back(a, b, w);
    g[b].emplace_back(b, a, w);
}
void add_arc(Graph &g, int a, int b, Weight w = 1) { g[a].emplace_back(a, b, w); }






map<string,int> varmaxi;
map<pair<string,int>,int> val;

void mpin(){
	varmaxi.clear();
	val.clear();
}

bool iseq(string &s){
	lp(i,s.size()){
		if(s[i]=='=')return true;
	}
	return false;
}

void stsep(string s,string &l,string &r){
	lp(i,s.size()){
		if(s[i]=='='){
			l=s.substr(0,i);
			r=s.substr(i+1,s.size()-i-1);
			return;
		}
	}
	assert(false);
}

pair<string,string> valsep(string s){
	lp(i,s.size()){
		if(s[i]=='['){
			string x,y;
			x=s.substr(0,i);
			y=s.substr(i+1,s.size()-i-2);
			return {x,y};		
		}
	}
	assert(false);
}

int valget(string s){
	pair<string,string> p=valsep(s);
	string x=p.first;
	string y=p.second;
	int num=stoi(y);
	if(varmaxi.find(x)==varmaxi.end()){
		return -1;
	}
	int maxi=varmaxi[x];
	if(num>=maxi){
		return -1;
	}
	if(val.find({x,num})==val.end()){
		return -1;
	}
	return val[{x,num}];
}
int valget(string x,string y){
	int num=stoi(y);
	if(varmaxi.find(x)==varmaxi.end()){
		return -1;
	}
	int maxi=varmaxi[x];
	if(num>=maxi){
		return -1;
	}
	if(val.find({x,num})==val.end()){
		return -1;
	}
	return val[{x,num}];
}
bool isd(string s){
	lp(i,s.size()){
		if('0'<=s[i]&&s[i]<='9')continue;
		return false;
	}
	return true;
}

int solr(string s){
	//cout<<s<<endl;
	if (isd(s)){
		return stoi(s);
	}
	else{
		string x,y;
		pair<string,string> p=valsep(s);
		x=p.first;
		y=p.second;
		y=to_string(solr(y));
		return valget(x,y);
	}
}

int valset(string s,int num){
	string x,y;
	x=valsep(s).first;
	y=valsep(s).second;
	int v=stoi(y);
	if(varmaxi.find(x)==varmaxi.end())return -1;
	if(varmaxi[x]<=v)return -1;
	val[{x,v}]=num;
	return 0;
}

int soll(string s,int num){
	if (isd(s)){
		return stoi(s);
	}
	else{
		string x,y;
		pair<string,string> p=valsep(s);
		x=p.first;
		y=p.second;
		y=to_string(solr(y));
		if(y=="-1")return -1;
		s=x+"["+y+"]";
		return valset(s,num);
	}
}

bool solve(string l,string r){
	int x=solr(r);
	if(x==-1)return false;
	if(soll(l,x)==-1)return false;
	return true;
}

signed main(){
	while(1){
		mpin();
		int cnt=0;
		vector<string> v;
		while(1){
			string s;
			cin>>s;
			if(s==".")break;
			v.push_back(s);
		}
		if(v.empty())break;
		lp(i,v.size()){
			string s=v[cnt];
			cnt++;
			if(iseq(s)){
				string l,r;
				stsep(s,l,r);
				if(solve(l,r)==false){
					break;
				}
			}
			else{
				string x=valsep(s).first;
				string y=valsep(s).second;
				int n=stoi(y);
				varmaxi[x]=n;
			}
			if(i+1==v.size())cnt=0;
		}
		cout<<cnt<<endl;
	}
	return 0;
}
accuracy: 1
time_ms: 20
memory_kb: 3356
final_rank: 12

code_snippet: #include<iostream>
#include<map>

using namespace std;
using State = string::iterator;
class ParseError{};

map<char, int> vals;
map<pair<char, int>, int> assigns;
string line;

bool parse_declaration(State& begin);
bool parse_assignment(State& begin);
int parse_expression(State& begin);
int parse_number(State& begin);

void debug(State& begin, string msg) {
    cout << line << endl;
    int l = distance(line.begin(), begin);
    for (int i = 0; i < l; ++i) cout << " ";
    cout << "^ " << msg << endl;
}

bool parse_line(State& begin) {
    // debug(begin, "line");
    State start = begin;
    bool ret;
    try {
        ret = parse_declaration(begin);
    } catch(ParseError e) {
        begin = start;
        ret = parse_assignment(begin);
    }
    return ret;
}

bool is_digit(char c) {
    return c - '0' >= 0 && c - '0' <= 9;
}

void newline(State &begin) {
    if (begin != line.end()) throw ParseError();
}
void consume(State &begin, char c) {
    if (*begin != c) {
        // cout << line << endl;
        // debug(begin, string("expected ") + c + string(" but got ") + *begin);
        throw ParseError();
    }
    begin++;
}

bool parse_declaration(State& begin) {
    // debug(begin, "decl");
    char array_name = *begin;
    begin++;
    consume(begin, '[');
    int length = parse_number(begin);
    consume(begin, ']');
    newline(begin);
    vals[array_name] = length;
    return true;
}

bool parse_assignment(State& begin) {
    // debug(begin, "assi");
    char array_name = *begin;
    begin++;
    consume(begin, '[');
    int index = parse_expression(begin);
    if (index == -1) return false;
    consume(begin, ']');
    consume(begin, '=');
    int value = parse_expression(begin);
    newline(begin);
    if (value == -1) return false;
    if (index >= vals[array_name]) return false;
    auto key = make_pair(array_name, index);
    assigns[key] = value;
    return true;
}

int parse_expression(State& begin) {
    if (is_digit(*begin)) {
        return parse_number(begin);
    } else {
        char array_name = *begin;
        begin++;
        consume(begin, '[');
        int index = parse_expression(begin);
        consume(begin, ']');
        if (vals.find(array_name) != vals.end()) {
            auto key = make_pair(array_name, index);
            if (assigns.find(key) != assigns.end()) {
                return assigns[key];
            } else {
                return -1;
            }
        } else {
            return -1;
        }
    }
}


int parse_number(State& begin) {
    int ret = 0;
    while(*begin - '0' >= 0 && *begin - '0' <= 9) {
        ret *= 10;
        ret += *begin - '0';
        begin++;
    }
    return ret;
}

int main() {
    int cnt = 0;
    int lc = 1;
    int ans = 0;
    while(1) {
        cin >> line;
        if (line == ".") {
            cout << ans << endl;
            vals.clear();
            assigns.clear();
            lc = 1;
            ans = 0;
            cin >> line;
            if (line == ".") break;
        } else {
            cnt = 0;
        }
        if (ans == 0) {
            State begin = line.begin();
            if (!parse_line(begin)) {
                ans = lc;
            }
        }
        lc++;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3260
final_rank: 6

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
typedef pair<int,P> P1;
typedef pair<P,P> P2;
#define pu push
#define pb push_back
#define mp make_pair
#define eps 1e-7
#define INF 1000000000
#define mod 1000000007
#define fi first
#define sc second
#define rep(i,x) for(int i=0;i<x;i++)
#define repn(i,x) for(int i=1;i<=x;i++)
#define SORT(x) sort(x.begin(),x.end())
#define ERASE(x) x.erase(unique(x.begin(),x.end()),x.end())
#define POSL(x,v) (lower_bound(x.begin(),x.end(),v)-x.begin())
#define POSU(x,v) (upper_bound(x.begin(),x.end(),v)-x.begin())
string str;
map<char,ll>M;
map<pair<char,ll>,ll>MM;
ll expr(string str){
	if('0' <= str[0] && str[0] <= '9'){
		ll ret = 0;
		rep(i,str.size()) ret = ret*10LL+str[i]-'0';
		return ret;
	}
	else{
		char id = str[0];
		string nw = "";
		for(int i=2;i<str.size()-1;i++) nw.pb(str[i]);
		ll in = expr(nw);
		if(in > 1e17) return 1e18;
		if(M[id] <= in) return 1e18;
		if(0 > in) return 1e18;
		if(MM.find(mp(id,in)) == MM.end()) return 1e18;
		return MM[mp(id,in)];
	}
}
int main(){
	while(1){
		cin>>str;
		if(str == ".") return 0;
		M.clear(); MM.clear();
		vector<string>vec; vec.pb(str);
		while(1){
			cin>>str;
			if(str == ".") break;
			vec.pb(str);
		}
		rep(i,vec.size()){
			string par = vec[i];
			int pos = -1;
			rep(j,par.size()){
				if(par[j] == '=') pos = j;
			}
			if(pos == -1){
				//declaration
				char id = par[0];
				ll num = 0;
				for(int i=2;i<par.size()-1;i++){
					num = num*10+par[i]-'0';
				}
				M[id] = num;
			}
			else{
				string le="",ri="";
				for(int j=2;j<pos-1;j++) le.pb(par[j]);
				for(int j=pos+1;j<par.size();j++) ri.pb(par[j]);
				ll assign_val = expr(ri);
				char id = par[0];
				ll index = expr(le);
				//cout << index << " " << id << " " << assign_val << endl;
				if(index > 1e17 || index >= M[id] || index < 0 || assign_val > 1e17){
					cout << i+1 << endl;
					goto fail;
				}
				MM[mp(id,index)] = assign_val;
			}
		}
		cout << 0 << endl;
		fail:;
	}
}
accuracy: 1
time_ms: 10
memory_kb: 3316
final_rank: 7

code_snippet: #include <bits/stdc++.h>
#define int long long
using namespace std;
using ld = long double;

template <class T, class U>
bool contains(const map<T, U> &mp, const T &key) {
    return mp.find(key) != mp.end();
}

struct State {
    int idx;
    int line;
    vector<string> s;
};

struct Expr {
    enum Type {
        IMV,
        ARRAY,
    } type;
    int value;
    char arr_name;
    Expr *num;
    static Expr *from_int(int x) {
        return new Expr {Type::IMV, x, '\0', nullptr};
    }
};

struct Statement {
    enum Type {
        DECL,
        ASSIGN,
    } type;
    char arr_name;
    Expr *num;
    Expr *value;
};

char get_char(State &st) {
    if ((int)st.s[st.line].size() <= st.idx) return '\n';
    return st.s[st.line][st.idx];
}

bool is_digit(State &st) {
    return '0' <= get_char(st) && get_char(st) <= '9';
}

int parse_num(State &st) {
    string num = "";
    while (is_digit(st)) {
        num += get_char(st);
        st.idx += 1;
    }
    int ret = stoll(num);
    return ret;
}

Expr *parse_expr(State &st) {
    if (is_digit(st)) {
        return Expr::from_int(parse_num(st));
    } else {
        Expr *expr = new Expr();
        expr->type = Expr::Type::ARRAY;
        expr->arr_name = get_char(st);
        st.idx += 2;
        expr->num = parse_expr(st);
        st.idx += 1;
        return expr;
    }
}

vector<Statement> parse_program(State &st) {
    vector<Statement> statements;
    while (st.line < (int)st.s.size()) {
        Statement s;
        s.arr_name = get_char(st);
        st.idx += 2;
        s.num = parse_expr(st);
        st.idx += 1;
        if (get_char(st) == '\n') {
            s.type = Statement::Type::DECL;
        } else {
            st.idx += 1;
            s.type = Statement::Type::ASSIGN;
            s.value = parse_expr(st);
        }
        st.line++;
        st.idx = 0;
        statements.push_back(s);
    }
    return statements;
}

map<char, int> arr_size;
map<char, map<int, int>> arr_data;
bool eval_expr(Expr &expr, int &ret) {
    if (expr.type == Expr::Type::IMV) {
        ret = expr.value;
        return true;
    } else {
        int num;
        bool valid = eval_expr(*expr.num, num);
        if (!valid) return false;
        if (!contains(arr_size, expr.arr_name)) return false;
        if (!(0 <= num && num < arr_size[expr.arr_name])) return false;
        if (!contains(arr_data[expr.arr_name], num)) return false;
        ret = arr_data[expr.arr_name][num];
        return true;
    }
}
bool eval_statement(Statement &s) {
    if (s.type == Statement::Type::DECL) {
        int num;
        bool valid = eval_expr(*s.num, num);
        if (!valid) return false;
        arr_size[s.arr_name] = num;
    } else {
        if (!contains(arr_size, s.arr_name)) return false;
        int num, value;
        bool valid = eval_expr(*s.num, num);
        if (!valid) return false;
        if (!(0 <= num && num < arr_size[s.arr_name])) return false;
        valid = eval_expr(*s.value, value);
        if (!valid) return false;
        arr_data[s.arr_name][num] = value;
    }
    return true;
}
int check_program(vector<Statement> &prog) {
    int ans = 0;
    for (int i = 0; i < (int)prog.size(); i++) {
        auto &s = prog[i];
        if (!eval_statement(s)) {
            ans = i + 1;
            break;
        }
    }
    return ans;
}

signed main() {
    while (1) {
        arr_size.clear();
        arr_data.clear();
        string s;
        cin >> s;
        if (s == ".") break;

        State state = {0, 0, {}};
        state.s.push_back(s);
        while (1) {
            cin >> s;
            if (s == ".") break;
            state.s.push_back(s);
        }
        auto prog = parse_program(state);
        cout << check_program(prog) << endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 5228
final_rank: 15

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <string>
#include <utility>
using namespace std;
typedef pair<string, string> pss;

map<string, map<int, int> > arrays;
map<string, int> limit;
bool isdeclare(string &s){
	for(int i=0; i<(int)s.length(); i++){
		if(s[i]=='=') return false;
	}
	return true;
}
int tonum(string &s){
	for(int i=0; i<(int)s.length(); i++){
		if(s[i] < '0' || '9' < s[i]){
			return -1;
		}
	}
	return stoi(s);
}
pss parsebrac(string &s){
	int n = s.length();
	int i=0;
	while(s[i]!='[') i++;
	return make_pair(s.substr(0, i), s.substr(i+1, n-i-2));
}
pss parseeq(string &s){
	int n = s.length();
	int i=0;
	while(s[i]!='=') i++;
	return make_pair(s.substr(0, i), s.substr(i+1, n-i-1));
}
int getnum(string &s){
	if(tonum(s)!=-1) return tonum(s);
	pss pstr = parsebrac(s);
	int idx = getnum(pstr.second);
	string name = pstr.first;
	if(arrays[name].find(idx) != arrays[name].end()){
		return arrays[name][idx];
	}
	return -1;
}

int main(){
	while(1){
		bool end = false;
		int ans = 0;
		arrays = map<string, map<int, int> >();
		limit = map<string, int>();
		for(int line=1; ; line++){
			string str;
			cin >> str;
			if(str == "."){
				if(line == 1) end = true;
				break;
			}
			if(ans != 0) continue;
			
			if(isdeclare(str)){
				pss pstr = parsebrac(str);
				limit[pstr.first] = tonum(pstr.second);
				arrays[pstr.first] = map<int, int>();
			}else{
				pss pstr1 = parseeq(str);
				int val = getnum(pstr1.second);
				pss pstr2 = parsebrac(pstr1.first);
				int subsidx = getnum(pstr2.second);
				string subsname = pstr2.first;
				if(val!=-1 && subsidx!=-1 && limit[subsname]>subsidx){
					arrays[subsname][subsidx] = val;
				}else{
					ans = line;
				}
			}
		}
		if(end) break;
		cout << ans << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3228
final_rank: 3

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
#include <map>
#include <string>
#include <utility>
using namespace std;
typedef pair<string, string> pss;

map<string, map<int, int> > name;
map<string, int> limit;
bool isdeclare(string &s){
	for(int i=0; i<(int)s.length(); i++){
		if(s[i]=='=') return false;
	}
	return true;
}
int tonum(string &s){
	for(int i=0; i<(int)s.length(); i++){
		if(s[i] < '0' || '9' < s[i]){
			return -1;
		}
	}
	return stoi(s);
}
pss divbrac(string &s){
	int n = s.length();
	int i=0;
	while(s[i]!='[') i++;
	return make_pair(s.substr(0, i), s.substr(i+1, n-i-2));
}
pss diveq(string &s){
	int n = s.length();
	int i=0;
	while(s[i]!='=') i++;
	return make_pair(s.substr(0, i), s.substr(i+1, n-i-1));
}
int getnum(string &s){
	if(tonum(s)!=-1) return tonum(s);
	pss parse = divbrac(s);
	int idx = getnum(parse.second);
	string arrayname = parse.first;
	if(name[arrayname].find(idx) != name[arrayname].end()){
		return name[arrayname][idx];
	}
	return -1;
}

int main(){
	while(1){
		bool end = false;
		int ans = 0;
		name = map<string, map<int, int> >();
		limit = map<string, int>();
		for(int line=1; ; line++){
			string str;
			cin >> str;
			if(str == "."){
				if(line == 1) end = true;
				break;
			}
			if(ans != 0) continue;
			
			if(isdeclare(str)){
				pss parse = divbrac(str);
				limit[parse.first] = tonum(parse.second);
				name[parse.first] = map<int, int>();
			}else{
				pss parse = diveq(str);
				int val = getnum(parse.second);
				pss parse2 = divbrac(parse.first);
				int subidx = getnum(parse2.second);
				string subarray = parse2.first;
				if(val!=-1 && subidx!=-1 && limit[subarray]>subidx){
					name[subarray][subidx] = val;
				}else{
					ans = line;
				}
			}
		}
		if(end) break;
		cout << ans << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3228
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;

class arrayInfo{
  private:
    int element=-1;
    map<string,string> value;
  public:
    bool isInRange(string index){
        return stoi(index)<element;
    }
    void set(string index, string val){
        if(isInRange(index)){
            value[index]=val;
        }else{
            throw 1;
        }
    }
    string get(string index){
        if(isInRange(index) && value.find(index)!=value.end()){
            return value[index];
        }else{
            throw 1;
        }
    }
    void setRange(string range){
        if(element==-1){
            element=stoi(range);
        }else{
            throw 1;
        }
    }
};
#define all(a) a.begin(),a.end()
#define rall(a) a.rbegin(),a.rend()

map<string, arrayInfo> ar;

string parse(string str, string type){
    int l,r;
    if(str.find("[")!=string::npos){
        l=str.find("[");
        r=str.rfind("]");
        if(type=="name") return str.substr(0,l);
        if(type=="index") return parse(str.substr(l+1,r-l-1), "value");
        if(type=="value") return ar[str.substr(0,l)].get(parse(str.substr(l+1,r-l-1), "value"));
    }
    return str;
}

int main(void){
    while(true){
        ar.erase(ar.begin(),ar.end());
        //cout<<"=========\n";
        string ln;
        cin>>ln;
        if(ln=="."){
            break;
        }
        int n=1;
        bool isOccured=false;
        while(ln!="."){
            try{
                if(ln.find("=")==string::npos){
                    ar[parse(ln,"name")].setRange(parse(ln,"index"));
                }else{
                    string ls=ln.substr(0,ln.find("="));
                    string rs=ln.substr(ln.find("=")+1);
                    ar[parse(ls,"name")].set(parse(ls,"index"),parse(rs,"value"));
                }
            }catch(...){
                isOccured=true;
                break;
            }
            n++;
            cin>>ln;
        }
        if(isOccured){
            cout<<n<<endl;
            while(cin>>ln,ln!=".");
        }else{
            cout<<0<<endl;
        }
    }
}
accuracy: 1
time_ms: 20
memory_kb: 3324
final_rank: 11

code_snippet: #include<string>
#include<sstream>
#include<iostream>
#include<map>
#include<vector>
#include<algorithm>
#include<cstdio>
//#include<bits/stdc++.h>
using namespace std;

vector<string> code;
map<string, int> val;
map<char, int> a;

int get_val(string str) {
	if(str.find("[") == string::npos) {
		stringstream ss(str);
		int v; ss >> v;
		return v;
	}
	if(count(str.begin(), str.end(), '[') == 1) {
		if(!val.count(str)) return -1;
		return val[str];
	}
	string cur = str.substr(str.find("[") + 1);
	int v = get_val(cur);
	stringstream ss;
	ss << v;
	string s; ss >> s;
	if(!val.count(str.substr(0, 2) + s)) return -1;
	return val[str.substr(0, 2) + s];
}
void add_arr(const string str) {
	stringstream ss(str.substr(2));
	int v; ss >> v;
	a[str[0]] = v;
}
int main() {
	ios::sync_with_stdio(false);
	string line, l, r, name;
	int rval, lval, bug;
	while(code.clear(), val.clear(), a.clear(), bug = -1, true) {
		cin >> line;
		if(line == ".") break;
		while(true) {
			code.push_back(line);
			cin >> line;
			if(line == ".") break;
		}
		for(size_t i = 0; i != code.size(); i++) {
			if(code[i].find("=") == string::npos) 
				add_arr(code[i]);
			else {
				l = code[i].substr(0, code[i].find("="));
				r = code[i].substr(code[i].find("=") + 1);
				rval = get_val(r.substr(0, r.find("]")));
				lval = get_val(l.substr(l.find("[") + 1, l.find("]") - l.find("[") - 1));
				if(rval == -1 || lval == -1 || !a[code[i][0]] || lval >= a[code[i][0]]) {bug = i; break;}
				stringstream ss;
				ss << lval;
				string s; ss >> s;
				name = code[i].substr(0, 2) + s;
				val[name] = rval;
			}
		}
		cout << bug + 1 << endl;
	}
	return 0;
}
accuracy: 1
time_ms: 30
memory_kb: 3336
final_rank: 13

code_snippet: #include <iostream>
#include <string>
#include <vector>
#include <map>
#include <cstdlib>
#include <cassert>
#include <algorithm>
#include <utility>
using namespace std;

#define fi first
#define se second
typedef long long ll;

ll recursive_parse(const string & s, int & indx, map<string,ll>& symbol_table, map<pair<string,ll>,ll>& vals) {
	if('0' <= s[indx] && s[indx] <= '9') {
		ll res = 0;
		while(s[indx] != ']' && indx < s.size()) {
			res *= 10;
			res += s[indx]-'0';
			indx++;
		}
		return res;
	}
	string symbol = "";
	while(s[indx] != '[') {
		symbol += s[indx];
		indx++;
	}
	indx++;
	ll num = recursive_parse(s, indx, symbol_table, vals);
	indx++;

	if(num < 0) return -1;
	if(vals.find(make_pair(symbol, num)) == vals.end() /*not assigned */
			|| num >= symbol_table[symbol] /* out of range*/) {
		return -1;
	}
	return vals[make_pair(symbol,num)];
}

int main() {
	while(1) {
		string s_tmp;
		vector<string> program;
		while(cin >> s_tmp, s_tmp != ".") {
			program.push_back(s_tmp);
		}
		if(!program.size()) {
			// end of the input
			break;
		}
		map<string,ll> symbol_table;
		map<pair<string,ll>,ll> vals;
		int res = 0;
		for(int line = 0; line < program.size(); line++) {
			string s = program[line];
			if(s.find('=') == string::npos) {
				string symbol = string(s.begin(), s.begin() + s.find('['));
				ll size = atol(string(s.begin() + s.find('[')+1, s.begin() + s.find(']')).c_str());
				symbol_table[symbol] = size;
			}
			else {
				string l = string(s.begin(), s.begin()+s.find('='));
				string r = string(s.begin()+s.find('=')+1, s.end());
				ll l_val, r_val;

				int arg_indx = 0;
				string symbol = string(l.begin(), l.begin() + l.find('['));
				arg_indx = l.find('[')+1;

				l_val = recursive_parse(l,arg_indx,symbol_table,vals);
				assert(arg_indx+1 == l.size());
				arg_indx = 0;
				r_val = recursive_parse(r,arg_indx,symbol_table,vals);
				assert(arg_indx == r.size());

				if(l_val < 0 || r_val < 0 || symbol_table.find(symbol) == symbol_table.end() 
						|| symbol_table[symbol] <= l_val) {
					res = line+1;
					break;
				}

				vals[make_pair(symbol, l_val)] = r_val;
			}
		}
		cout << res << endl;
	}
}
accuracy: 1
time_ms: 10
memory_kb: 3364
final_rank: 8

code_snippet: #include "bits/stdc++.h"
using namespace std;

#define rep(i, n) for (int i = 0; i < (n); i ++) 

vector<pair<map<int, int>, int>> p(52);

int get_value(string x) {
        if ('0' <= x[0] && x[0] <= '9') {
                return stoi(x);
        }
        if (p[x[0] + (x[0] <= 'Z' ? -'A' : 26 - 'a')].second == 0) return -1;
        string in = x.substr(2, x.size() - 3);
        int index = get_value(in);
        if (index == -1) return -1;
        if (p[x[0] + (x[0] <= 'Z' ? -'A' : 26 - 'a')].second - 1 < index) return -1;
        auto it = p[x[0] + (x[0] <= 'Z' ? -'A' : 26 - 'a')].first.find(index);
        if (it == p[x[0] + (x[0] <= 'Z' ? -'A' : 26 - 'a')].first.end()) return -1;
        return p[x[0] + (x[0] <= 'Z' ? -'A' : 26 - 'a')].first[index];
}

int main() {
        bool end = false;
        while (true) {
                int ans = 0, cnt = 0;
                p.clear();
                p.resize(52);
                for (int i = 0; i < 52; i ++) p[i].second = 0;
                bool found = false;
                while (true) {
                        cnt ++;
                        string s;
                        cin >> s;
                        if (s == "." && end) { 
                                goto fin;
                        }
                        if (s == ".") { 
                                break;
                        }
                        end = false;
                        bool eq = false;
                        for (int i = 0; i < s.size(); i ++) if (s[i] == '=') eq = true;
                        if (!eq) {
                                char alph = s[0];
                                s = s.substr(2, s.size() - 3);
                                p[alph + (alph <= 'Z' ? -'A' : 26 - 'a')].second = stoi(s);
                        } else {
                                //cerr << "eq" << endl;
                                string left, right;
                                int sp = 0;
                                while (s[sp] != '=') sp ++;
                                left = s.substr(0, sp);
                                right = s.substr(sp + 1);
                                //cerr << left << ' ' << right << endl;
                                int res = get_value(right);
                                //cerr << "res = " << res << endl;
                                int index = get_value(left.substr(2, left.size() - 3)); 
                                //cerr << res << ' ' << index << endl;
                                if ((res == -1 || index == -1) && !found) {
                                        //cerr << "found" << endl;
                                        ans = cnt;
                                        found = true;
                                }
                                if (p[left[0] + (left[0] <= 'Z' ? -'A' : 26 - 'a')].second - 1 < index && !found) {
                                        ans = cnt;
                                        found = true;
                                }
                                p[left[0] + (left[0] <= 'Z' ? -'A' : 26 - 'a')].first[index] = res;
                        }
                }
                cout << ans << endl;
                end = true;
        }
        fin:;
        return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3212
final_rank: 1

code_snippet: #include "bits/stdc++.h"
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<string,int> psi;
#define rep(i,n) for(ll i=0;i<(ll)(n);i++)
#define rep2(i,a,b) for(ll i=(a);i<(b);i++)
#define all(a)  (a).begin(),(a).end()
#define pb emplace_back
#define INF 2147483647
//#define INF (1LL<<59)

typedef string::const_iterator State;


map<psi,int> arr;
map<string,int> a_size;

int get_num(psi x){
    if(x.first=="NUMBER")return x.second;
    else{
        assert(arr.count(x)!=0);
        return arr[x];
    }
}


int num(State &beg){
    int ret = 0;
    while( isdigit(*beg) ){
        ret*=10;
        ret+=*beg-'0';
        beg++;
    }
    return ret;
}


psi eval(State &beg){
    psi ret;
    if( isdigit(*beg) ){
        int p = num(beg);
        return psi("NUMBER",p);
    }
    
    ret.first = *beg;   //テゥツ?催・ツ按療・ツ青?
    beg++;
    
    assert(*beg=='[');
    beg++;
    
    psi res = eval(beg);
    
    assert(*beg==']');
    beg++;
    
    if( res.first == "NUMBER" ){
        ret.second = res.second;
    }else{
        if(a_size.count(res.first)==0)throw -13;   //ティツゥツイテ・ツスツ禿ゥツ?催・ツ按療ァツ?。テ」ツ??
        if(a_size[res.first]<=res.second)throw -23;  //テゥツ?催・ツ按療・ツ、ツ姪・ツ渉づァツ?ァ
        
        if( arr.count(res)==0 )throw -33; //テヲツ慊ェテ・ツョツ堙ァツセツゥテ・ツ?、テ・ツ渉づァツ?ァ
        
        ret.second = get_num(res);
    }
    return ret;
}

int main(){
    string s;
    while(cin>>s && s!="."){
        arr.clear();
        a_size.clear();
        vector<string> vs;
        vs.pb(s);
        while(cin>>s && s!=".") vs.pb(s);
        
        bool f=false;
        
        rep(i,vs.size()){
            int pos = -1;
            rep(j,vs[i].size()){
                if(vs[i][j] == '=')pos = j;
            }
            
            if( pos==-1 ){
                State beg = vs[i].begin();
                psi res = eval(beg);
                a_size[res.first] = res.second;
                
            }else{
                string l = vs[i].substr(0,pos);
                string r = vs[i].substr(pos+1);
                try{
                    State beg = l.begin();
                    psi L = eval(beg);
                    
                    beg = r.begin();
                    psi R = eval(beg);
                    
                    if(a_size.count(L.first)==0)throw -11;   //ティツゥツイテ・ツスツ禿ゥツ?催・ツ按療ァツ?。テ」ツ??
                    if(a_size[L.first]<=L.second)throw -21;  //テゥツ?催・ツ按療・ツ、ツ姪・ツ渉づァツ?ァ

                    if(R.first != "NUMBER" && a_size.count(R.first)==0)throw -12;   //ティツゥツイテ・ツスツ禿ゥツ?催・ツ按療ァツ?。テ」ツ??
                    if(R.first != "NUMBER" && a_size[R.first]<=R.second)throw -22;  //テゥツ?催・ツ按療・ツ、ツ姪・ツ渉づァツ?ァ
                    if(R.first != "NUMBER" && arr.count(R)==0 )throw -31; //テヲツ慊ェテ・ツョツ堙ァツセツゥテ・ツ?、テ・ツ渉づァツ?ァ
                    
                    arr[psi(L)] = get_num(R);
                }catch(int excep){
                    cout<<i+1<<endl;
                    f = true;
                    break;
                }
            }
        }
        if(!f)cout<<0<<endl;
    }
}
accuracy: 1
time_ms: 10
memory_kb: 3368
final_rank: 9

code_snippet: #include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>

#define REP(i,s,n) for(int i=(int)(s);i<(int)(n);i++)

using namespace std;
typedef long long int ll;
typedef vector<int> VI;
typedef vector<ll> VL;
typedef pair<int, int> PI;

PI parse_num(string expr) {
  int cur = 0;
  int pos = 0;
  int n = (int) expr.length();
  while (pos < n) {
    if (not isdigit(expr[pos])) {
      return pos == 0 ? PI(-1, -1) : PI(pos, cur);
    }
    cur *= 10;
    cur += expr[pos] - '0';
    pos++;
  }
  return n == 0 ? PI(-1, -1) : PI(n, cur);
}

PI eval_decl(map<string, int> &ary, 
	     map<string, map<int, int> > &asgn,
	     string expr) {
  int n = expr.length();
  string an = expr.substr(0, 1);
  if (n <= 2 || expr[1] != '[') {
    return PI(-1, -1);
  }
  PI sz = parse_num(expr.substr(2));
  if (sz.first == -1) {
    return PI(-1, -1);
  }
  int len = sz.first + 2;
  if (n <= len || expr[len] != ']') {
    return PI(-1, -1);
  }
  // Should be exact
  if (n != len + 1) {
    return PI(-1, -1);
  }
  ary[an] = sz.second;
  return PI(len + 1, 0);
}

PI eval_expr(map<string, int> &ary, 
	     map<string, map<int, int> > &asgn,
	     string expr) {
  PI num = parse_num(expr);
  if (num.first >= 0) {
    return num;
  }
  // a[idx]
  string an = expr.substr(0, 1);
  int n = expr.length();
  if (n <= 2 || expr[1] != '[') {
    return PI(-1, -1);
  }
  PI idx = eval_expr(ary, asgn, expr.substr(2));
  if (idx.first == -1) {
    return PI(-1, -1);
  }
  int len = 2 + idx.first;
  if (n <= len || expr[len] != ']') {
    return PI(-1, -1);
  }
  if (ary.count(an) == 0) {
    return PI(-1, -1);
  }
  int arylen = ary[an];
  if (idx.second < 0 || idx.second >= arylen || asgn[an].count(idx.second) == 0) {
    return PI(-1, -1);
  }
  return PI(len + 1, asgn[an][idx.second]);
  
}

PI eval_asgn(map<string, int> &ary, 
	     map<string, map<int, int> > &asgn,
	     string expr) {
  string an = expr.substr(0, 1);
  int n = expr.length();
  if (n <= 2 || expr[1] != '[') {
    return PI(-1, -1);
  }
  PI idx = eval_expr(ary, asgn, expr.substr(2));
  if (idx.first == -1) {
    return PI(-1, -1);
  }
  int len = 2 + idx.first;
  if (n <= len + 1 || expr[len] != ']' || expr[len + 1] != '=') {
    return PI(-1, -1);
  }
  PI elem = eval_expr(ary, asgn, expr.substr(len + 2));
  if (elem.first == -1) {
    return PI(-1, -1);
  }
  if (ary.count(an) == 0) {
    return PI(-1, -1);
  }
  int arylen = ary[an];
  if (idx.second < 0 || idx.second >= arylen) {
    return PI(-1, -1);
  }
  asgn[an][idx.second] = elem.second;
  return PI(len + 2 + elem.first, 0);
}

PI eval(map<string, int> &ary, 
	 map<string, map<int, int> > &asgn,
	 string expr) {
  PI res = eval_decl(ary, asgn, expr);
  if (res.first >= 0) {
    return res;
  }
  return eval_asgn(ary, asgn, expr);
}


void solve(const vector<string> &pool) {
  map<string, int> ary;
  map<string, map<int, int> > asgn;
  REP(i, 0, pool.size()) {
    PI res = eval(ary, asgn, pool[i]);
    if (res.first == -1) {
      cout << i + 1 << "\n";
      return;
    }
  }
  cout << 0 << "\n";
}


int main(void) {
  ios::sync_with_stdio(false);
  cin.tie(0);
  vector<string> pool;
  string cur;
  while(cin >> cur) {
    if (cur == ".") {
      if (pool.empty()) {
	return 0;
      }
      solve(pool);
      pool.clear();
    } else {
      pool.push_back(cur);
    }
  }
}
accuracy: 1
time_ms: 10
memory_kb: 3240
final_rank: 5