第一次见到题目里带了个BNF,有意思。基本就是STL的map、stack应用。解析求值就按着编译器的来。赋值语句的右值、左值的参数、声明语句的参数需要求值到底,其余语句保留。栈arr用于存储当前操作的数组名,不过其实也可以不用栈。判断的函数可以内联,但是直接写出来更加清晰。
#include <iostream>
#include <map>
#include <string>
#include <stack>
using namespace std;
bool isArrayName(char c) {
return 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z';
}
bool isNum(char c) {
return '0' <= c && c <= '9';
}
string line;
map<char, map<int, int>> env;
map<char, int> sizes;
stack<char> arr; int num;
bool validInd() {
char n = arr.top();
return env.count(n) > 0 && 0 <= num && num < sizes[n];
}
bool parse(int st, int ed, bool rt) {
int pEnd = st; bool bug;
if (isArrayName(line[st])) {
arr.push(line[st]);
if (bug = parse(st + 2, ed - 1, true)) return true;
if (rt) { // Query
if (!validInd() || env[arr.top()].count(num) == 0)
return true;
num = env[arr.top()][num];
arr.pop();
}
} else {
// num
while (++pEnd < ed && isNum(line[pEnd]));
num = stoi(line.substr(st, pEnd));
}
return false;
}
int main() {
int posEq, lineCnt = 0, rValue; bool flag = false, bug = false;
while (cin >> line) {
if (line[0] == '.') {
if (flag) break;
env.clear();
sizes.clear();
if (!bug) cout << 0 << endl;
else if (lineCnt) cout << lineCnt << endl;
lineCnt = 0;
flag = true; bug = false;
continue;
}
flag = false;
if (bug) continue;
// Read
posEq = 0; lineCnt++;
while (++posEq < line.size() && line[posEq] != '=');
if (posEq == line.size()) {
// declaration
if (bug = parse(0, line.size() - 1, false))
continue;
sizes[arr.top()] = num;
env[arr.top()] = map<int, int>();
arr.pop();
} else {
// rt
if (bug = parse(posEq + 1, line.size() - 1, true))
continue;
rValue = num;
if (bug = parse(0, posEq, false)) continue;
if (bug = !validInd()) continue;
env[arr.top()][num] = rValue;
arr.pop();
}
}
return 0;
}