语法分析#
#include <bits/stdc++.h>
using namespace std;
vector<string> key, identify, symbol;
unordered_map<string, int> key_map, identify_map, symbol_map;
unordered_map<string, int> letter_map;
int key_offset = 1;
int symbol_offset = 12;
struct node {
int type;
string val;
};
const int numbers_type = 27;
const int identify_type = 26;
vector<node> tokens;
int index = 0;
void init() {
string str_key = "begin end if then while do const var call procedure odd", s;
string str_symbol = "+ - * / = # < > := ( ) , . ;";
stringstream key_in;
key_in << str_key;
while (key_in >> s) {
key.push_back(s);
key_map[s] = int(key.size()) - 1;
letter_map[s] = int(key.size()) - 1 + key_offset;
}
stringstream symbolin;
symbolin << str_symbol;
while (symbolin >> s) {
symbol.push_back(s);
symbol_map[s] = int(symbol.size()) - 1;
letter_map[s] = int(symbol.size()) - 1 + symbol_offset;
}
}
void read(vector<string> &ans) {
if (not ans.empty()) ans.clear();
string str, res, s;
while (getline(cin, str)) {
if (str.find("//") != string::npos) {
str.erase(str.find("//"));
}
res += str; res.push_back('\n');
}
stringstream ss; ss << res;
int flag = 1;
while (ss >> s) {
if (s == "(*") flag ^= 1;
if (flag) {
ans.push_back(s);
}
if (s == "*)") flag ^= 1;
}
}
void LexicalAnalysis(vector<string> &str, vector<node> &ans) {
if (not ans.empty()) ans.clear();
for (string s: str) {
if (key_map.count(s)) {
ans.push_back({letter_map[s], "-"});
} else if (symbol_map.count(s)) {
if (int(s.size()) > 10) {
cout << "symbol's size is too long!\n";
assert(false);
}
ans.push_back({letter_map[s], "-"});
} else if (identify_map.count(s)) {
ans.push_back({identify_type, to_string(identify_map[s])});
} else {
int ns = s.size();
for (int i = 0; i < ns; i ++ ) {
if (isdigit(s[i])) {
string t; t += s[i];
int j = i; while (j + 1 < ns and isdigit(s[j + 1])) {
++ j;
t += s[j];
}
ans.push_back({numbers_type, t});
i = j;
} else if (isalpha(s[i])) {
string t; t += s[i];
int j = i; while (j + 1 < ns and (isalpha(s[j + 1]) or isdigit(s[j + 1]))) {
++ j;
t += s[j];
}
if (key_map.count(t)) {
ans.push_back({letter_map[t], "-"});
} else {
if (int(t.size()) > 10) {
cout << "identify's size is too long!\n";
assert(false);
}
if (!identify_map.count(t)) {
identify.push_back(t);
int new_val = (int)identify.size() - 1;
identify_map[t] = new_val;
}
ans.push_back({identify_type, to_string(identify_map[t])});
}
i = j;
} else {
string t; t += s[i];
if (symbol_map.count(t)) {
ans.push_back({letter_map[t], "-"});
} else {
if (i + 1 >= (int)s.size()) {
cout << "illegal!\n";
assert(false);
}
t += s[++ i];
if (symbol_map.count(t)) {
ans.push_back({letter_map[t], "-"});
} else {
assert(false);
}
}
}
}
}
}
}
bool isDigit(string s) {
if (s[0] == '-') {
reverse(s.begin(), s.end());
s.pop_back();
reverse(s.begin(), s.end());
if (s == "0") return false;
}
if (s.empty()) return false;
if (s[0] == '0') {
return int(s.size()) == 1;
} else {
for (auto c: s) if (c < '0' or c > '9') return false;
}
return true;
}
string get_str(node &nd);
void exception_print(int type, string expected);
void match(string expected);
void match(string expected, bool majority);
void parse_program();
void parse_block();
void parse_constdecl();
void parse_constitem();
void parse_vardecl();
void parse_procdecl();
void parse_statement();
void parse_assignstmt();
void parse_callstmt();
void parse_compstmt();
void parse_ifstmt();
void parse_whilestmt();
void parse_condition();
void parse_expression();
void parse_term();
void parse_factor();
void parse_ident();
void parse_number();
bool success = true;
string symbolarray[] = { "=", "#", "<", ">" };
int symbollength = 4;
string get_str (node &nd) {
auto [type, val] = nd;
if (type >= 1 and type <= 11) {
return key[type - key_offset];
} else if (type >= 12 and type <= 25) {
return symbol[type - symbol_offset];
} else if (type == 26) {
return identify[stoi(val)];
} else if (type == 27) {
return val;
} else {
assert(false);
}
return "error";
}
void exception_print(int type, string expected = "") {
string ret;
if (type == 0) {
ret = "语法错误:预期为 " + expected + ",但输入的是 " + get_str(tokens[index]);
} else if (type == 1) {
ret = "标识符 " + get_str(tokens[index]) + " 格式错误";
} else if (type == 2) {
ret = "整数 " + get_str(tokens[index]) + "格式错误";
}
cout << ret << "\n";
success = false;
exit(100);
}
void match(string expected) {
if (get_str(tokens[index]) == expected) {
index++;
} else {
exception_print(0, expected);
}
}
void match(string expected, bool majority) {
bool iseuqal = false;
for (int i = 0; i < symbollength; i++) {
if (get_str(tokens[index]) == symbolarray[i]) {
index += 1; iseuqal = true; break;
}
expected += symbolarray[i];
if (i != symbollength - 1) {
expected += " ";
}
}
if (!iseuqal) {
exception_print(0, expected);
}
}
void parse_program() {
parse_block();
match(".");
}
void parse_block() {
parse_constdecl();
parse_vardecl();
parse_procdecl();
parse_statement();
}
void parse_constdecl() {
if (get_str(tokens[index]) == "const") {
match("const");
parse_constitem();
while (get_str(tokens[index]) == ",") {
match(",");
parse_constitem();
}
match(";");
}
}
void parse_constitem() {
parse_ident();
match("=");
parse_number();
}
void parse_vardecl() {
if (get_str(tokens[index]) == "var") {
match("var");
parse_ident();
while (get_str(tokens[index]) == ",") {
match(",");
parse_ident();
}
match(";");
}
}
void parse_procdecl() {
while (get_str(tokens[index]) == "procedure") {
match("procedure");
parse_ident();
match(";");
parse_block();
match(";");
}
}
void parse_statement() {
if (identify_map.count(get_str(tokens[index]))) {
parse_assignstmt();
} else if (get_str(tokens[index]) == "call") {
parse_callstmt();
} else if (get_str(tokens[index]) == "begin") {
parse_compstmt();
} else if (get_str(tokens[index]) == "if") {
parse_ifstmt();
} else if (get_str(tokens[index]) == "while") {
parse_whilestmt();
}
}
void parse_assignstmt() {
parse_ident();
match(":=");
parse_expression();
}
void parse_callstmt() {
match("call");
parse_ident();
}
void parse_compstmt() {
match("begin");
parse_statement();
while (get_str(tokens[index]) == ";") {
match(";");
parse_statement();
}
match("end");
}
void parse_ifstmt() {
match("if");
parse_condition();
match("then");
parse_statement();
}
void parse_whilestmt() {
match("while");
parse_condition();
match("do");
parse_statement();
}
void parse_condition() {
if (get_str(tokens[index]) == "odd") {
match("odd");
parse_expression();
} else {
parse_expression();
match("", true);
parse_expression();
}
}
void parse_expression() {
parse_term();
while (get_str(tokens[index]) == "+" || get_str(tokens[index]) == "-") {
match(get_str(tokens[index]));
parse_term();
}
}
void parse_term() {
parse_factor();
while (get_str(tokens[index]) == "*" || get_str(tokens[index]) == "/") {
match(get_str(tokens[index]));
parse_factor();
}
}
void parse_factor() {
if (get_str(tokens[index]) == "+" || get_str(tokens[index]) == "-") {
match(get_str(tokens[index]));
}
if (isDigit(get_str(tokens[index]))) {
parse_number();
} else if (identify_map.count(get_str(tokens[index]))) {
parse_ident();
} else {
match("(");
parse_expression();
match(")");
}
}
void parse_ident() {
if (identify_map.count(get_str(tokens[index]))) {
match(get_str(tokens[index]));
} else {
exception_print(1);
}
}
void parse_number() {
if (isDigit(get_str(tokens[index]))) {
match(get_str(tokens[index]));
} else {
exception_print(2);
}
}
bool GrammaticalAnalysis() {
parse_program();
if (success) {
cout << "语法正确" << endl;
}
return success;
}
int main() {
init();
vector<string> str;
read(str);
LexicalAnalysis(str, tokens);
GrammaticalAnalysis();
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现