第一次见到题目里带了个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; }