语法分析器(java转C++)
原:(46条消息) 语法分析器的设计与实现_雪琰焦糖的博客-CSDN博客_语法分析器
问题描述】
请根据给定的文法设计并实现语法分析程序,能基于上次作业的词法分析程序所识别出的单词,识别出各类语法成分。输入输出及处理要求如下:
(1)需按文法规则,用递归子程序法对文法中定义的所有种语法成分进行分析;
(2)为了方便进行自动评测,输入的被编译源文件统一命名为testfile.txt(注意不要写错文件名);输出的结果文件统一命名为output.txt(注意不要写错文件名);结果文件中包含如下两种信息:
1)按词法分析识别单词的顺序,按行输出每个单词的信息(要求同词法分析作业,对于预读的情况不能输出)。
2)在下列高亮显示的语法分析成分分析结束前,另起一行输出当前语法成分的名字,形如“<常量说明>”(注:未要求输出的语法成分仍需要分析)
【文法定义】
<加法运算符> ::= +|-
<乘法运算符> ::= *|/
<关系运算符> ::= <|<=|>|>=|!=|==
<字母> ::= _|a|...|z|A|...|Z
<数字> ::= 0|<非零数字>
<非零数字> ::= 1|...|9
<字符> ::= '<加法运算符>'|'<乘法运算符>'|'<字母>'|'<数字>'
<字符串> ::= "{十进制编码为32,33,35-126的ASCII字符}"
<程序> ::= [<常量说明>][<变量说明>]{<有返回值函数定义>|<无返回值函数定义>}<主函数>
<常量说明> ::= const<常量定义>;{ const<常量定义>;}
<常量定义> ::= int<标识符>=<整数>{,<标识符>=<整数>}
| char<标识符>=<字符>{,<标识符>=<字符>}
<无符号整数> ::= <非零数字>{<数字>}| 0
<整数> ::= [+|-]<无符号整数>
<标识符> ::= <字母>{<字母>|<数字>}
<声明头部> ::= int<标识符> |char<标识符>
<变量说明> ::= <变量定义>;{<变量定义>;}
<变量定义> ::= <类型标识符>(<标识符>|<标识符>'['<无符号整数>']'){,(<标识符>|<标识符>'['<无符号整数>']' )}
//<无符号整数>表示数组元素的个数,其值需大于0
<类型标识符> ::= int | char
<有返回值函数定义> ::= <声明头部>'('<参数表>')' '{'<复合语句>'}'
<无返回值函数定义> ::= void<标识符>'('<参数表>')''{'<复合语句>'}'
<复合语句> ::= [<常量说明>][<变量说明>]<语句列>
<参数表> ::= <类型标识符><标识符>{,<类型标识符><标识符>}| <空>
<主函数> ::= void main‘(’‘)’ ‘{’<复合语句>‘}’
<表达式> ::= [+|-]<项>{<加法运算符><项>} //[+|-]只作用于第一个<项>
<项> ::= <因子>{<乘法运算符><因子>}
<因子> ::= <标识符>|<标识符>'['<表达式>']'|'('<表达式>')'|<整数>|<字符>|<有返回值函数调用语句>
<语句> ::= <条件语句>|<循环语句>| '{'<语句列>'}'| <有返回值函数调用语句>;
|<无返回值函数调用语句>;|<赋值语句>;|<读语句>;|<写语句>;|<空>;|<返回语句>;
<赋值语句> ::= <标识符>=<表达式>|<标识符>'['<表达式>']'=<表达式>
<条件语句> ::= if '('<条件>')'<语句>[else<语句>]
<条件> ::= <表达式><关系运算符><表达式> //整型表达式之间才能进行关系运算
|<表达式> //表达式为整型,其值为0条件为假,值不为0时条件为真
<循环语句> ::= while '('<条件>')'<语句>| do<语句>while '('<条件>')' |for'('<标识符>=<表达式>;<条件>;<标识符>=<标识符>(+|-)<步长>')'<语句>
<步长>::= <无符号整数>
<有返回值函数调用语句> ::= <标识符>'('<值参数表>')'
<无返回值函数调用语句> ::= <标识符>'('<值参数表>')'
<值参数表> ::= <表达式>{,<表达式>}|<空>
<语句列> ::= {<语句>}
<读语句> ::= scanf '('<标识符>{,<标识符>}')'
<写语句> ::= printf '(' <字符串>,<表达式> ')'| printf '('<字符串> ')'| printf '('<表达式>')'
<返回语句> ::= return['('<表达式>')']
【输入形式】testfile.txt中的符合文法要求的测试程序。
【输出形式】按如上要求将语法分析结果输出至output.txt中,中文字符的编码格式要求是UTF-8。
【特别提醒】(1)本次作业只考核对正确程序的处理,但需要为今后可能出现的错误情况预留接口。
(2)当前要求的输出只是为了便于评测,完成编译器中无需出现这些信息,请设计为方便打开/关闭这些输出的方案。
【样例输入】
1 2 3 4 5 6 7 8 9 10 11 12 | const int const1 = 1, const2 = -100; const char const3 = '_' ; int change1; char change3; int gets1( int var1, int var2){ change1 = var1 + var2; return (change1); } void main(){ printf ( "Hello World" ); printf (gets1(10, 20)); } |
【样例输出】
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | CONSTTK const INTTK int IDENFR const1 ASSIGN = INTCON 1 <无符号整数> <整数> COMMA , IDENFR const2 ASSIGN = MINU - INTCON 100 <无符号整数> <整数> <常量定义> SEMICN ; CONSTTK const CHARTK char IDENFR const3 ASSIGN = CHARCON _ <常量定义> SEMICN ; <常量说明> INTTK int IDENFR change1 <变量定义> SEMICN ; CHARTK char IDENFR change3 <变量定义> SEMICN ; <变量说明> INTTK int IDENFR gets1 <声明头部> LPARENT ( INTTK int IDENFR var1 COMMA , INTTK int IDENFR var2 <参数表> RPARENT ) LBRACE { IDENFR change1 ASSIGN = IDENFR var1 <因子> <项> PLUS + IDENFR var2 <因子> <项> <表达式> <赋值语句> SEMICN ; <语句> RETURNTK return LPARENT ( IDENFR change1 <因子> <项> <表达式> RPARENT ) <返回语句> SEMICN ; <语句> <语句列> <复合语句> RBRACE } <有返回值函数定义> VOIDTK void MAINTK main LPARENT ( RPARENT ) LBRACE { PRINTFTK printf LPARENT ( STRCON Hello World <字符串> RPARENT ) <写语句> SEMICN ; <语句> PRINTFTK printf LPARENT ( IDENFR gets1 LPARENT ( INTCON 10 <无符号整数> <整数> <因子> <项> <表达式> COMMA , INTCON 20 <无符号整数> <整数> <因子> <项> <表达式> <值参数表> RPARENT ) <有返回值函数调用语句> <因子> <项> <表达式> RPARENT ) <写语句> SEMICN ; <语句> <语句列> <复合语句> RBRACE } <主函数> <程序><br><br> |
1 #include <iostream> 2 #include <vector> 3 #include <map> 4 #include <string> 5 #include <cstdio> 6 #include <cctype> 7 #include <regex> 8 #include <algorithm> 9 #include <fstream> 10 using namespace std; 11 //关键字 12 static vector<string> keyWordKey = {"const", "int", "char", "void", "main", "getint", "if", "else", "switch", "case", "default", "while", "for", "scanf", "printf", "return", "auto", "short", "long", "float", "double", "struct", "union", "enum", "typedef", "unsigned", "signed", "extern", "register", "static", "volatile", "do", "goto", "continue", "break", "sizeof"}; 13 14 //关键字种别码 15 static vector<string> keyWordValue = {"CONSTTK", "INTTK", "CHARTK", "VOIDTK", "MAINTK", "GETINTTK", "IFTK", "ELSETK", "SWITCHTK", "CASETK", "DEFAULTTK", "WHILETK", "FORTK", "SCANFTK", "PRINTFTK", "RETURNTK", "AUTOTK", "SHORTTK", "LONGTK", "FLOATTK", "DOUBLETK", "STRUCTTK", "UNIONTK", "ENUMTK", "TYPEDEFTK", "UNSIGNEDTK", "SIGNEDTK", "EXTERNTK", "REGISTERTK", "STATICTK", "VOLATILLETK", "DOTK", "GOTOTK", "CONTINUETK", "BREAKTK", "SIZEOFTK"}; 16 17 //运算符 18 static vector<string> operationKey = {"+", "-", "*", "/", "<", "<=", ">", ">=", "==", "!=", "="}; 19 //运算符种别码 20 static vector<string> operationValue = {"PLUS", "MINU", "MULT", "DIV", "LSS", "LEQ", "GRE", "GEQ", "EQL", "NEQ", "ASSIGN"}; 21 22 //界符 23 static vector<string> symbolKey = {":", ";", ",", "(", ")", "{", "}", "[", "]"}; 24 25 //界符种别码 26 static vector<string> symbolValue = {"COLON", "SEMICN", "COMMA", "LPARENT", "RPARENT", "LBRACE", "RBRACE", "LBRACK", "RBRACK"}; 27 28 //语法分析当前单词的种别码 29 static vector<string> Tokens; 30 //语法分析当前单词 31 static vector<string> vals; 32 33 //key为函数的方法名,Value值为1表示该方法是有返回值的方法 34 static map<string,int> NVoidFunction; 35 36 static map<string,string> keywords; 37 static map<string,string> operations; 38 static map<string,string> symbols; 39 40 //指向当前所读到字符串的位置的指针 41 static int p, lines; 42 43 //语法分析当前单词位置 44 static int q; 45 46 47 48 ofstream write("output.txt"); 49 ifstream read("testfile.txt"); 50 void lexAnalysing(string str); 51 void init(); 52 void digitCheck(string str); 53 void letterCheck(string str); 54 void stringCheck(string str); 55 void charCheck(string str); 56 void symbolCheck(string str); 57 void parsing(); 58 void parse0(); 59 void parse1(); 60 void parse2(); 61 void parse3(); 62 void parse4(); 63 void parse5(); 64 void parse6(); 65 void parse7(); 66 void parse8(); 67 void parse9(); 68 void parse10(); 69 void parse11(); 70 void parse12(); 71 void parse13(); 72 void parse14(); 73 void parse15(); 74 void parse16(); 75 void parse17(); 76 void parse18(); 77 void parse19(); 78 void parse20(); 79 void parse21(); 80 void parse22(); 81 void parse23(); 82 void parse234(); 83 void parse25(); 84 void parse26(); 85 void parse27(); 86 void parse28(); 87 void parse29(); 88 void MatchToken(string expected); 89 int main(){ 90 init(); 91 lines=1; 92 string line; 93 while(getline(read,line)){ 94 lexAnalysing(line); 95 lines++; 96 } 97 parsing(); 98 write.close(); 99 read.close(); 100 return 0; 101 } 102 void init(){ 103 for(int i=0;i<keyWordKey.size();i++){ 104 keywords[keyWordKey[i]]=keyWordValue[i]; 105 } 106 for(int i=0;i<operationKey.size();i++){ 107 operations[operationKey[i]]=operationValue[i]; 108 } 109 for(int i=0;i<symbolKey.size();i++){ 110 symbols[symbolKey[i]]=symbolValue[i]; 111 } 112 } 113 void lexAnalysing(string str) { 114 p=0; 115 char ch; 116 str.erase(0, str.find_first_not_of(' ')); 117 str.erase(str.find_last_not_of(' ')+1); 118 for(;p<str.length();p++){ 119 ch=str.at(p); 120 if(isdigit(ch)){ 121 digitCheck(str); 122 } 123 else if(isalpha(ch) || ch == '_'){ 124 letterCheck(str); 125 } 126 else if(ch == '"'){ 127 stringCheck(str); 128 } 129 else if(ch == '\''){ 130 charCheck(str); 131 } 132 else if(ch == ' '){ 133 continue; 134 } 135 else { 136 symbolCheck(str); 137 } 138 } 139 } 140 void digitCheck(string str) { 141 142 string token; 143 token.push_back(str.at(p++)); 144 //判断数字的小数点是否有且是否大于1 145 int flag = 0; 146 bool err = false; 147 char ch; 148 for (; p < str.length(); p++) { 149 ch = str.at(p); 150 if (ch == ' ' || (!isalnum(ch) && ch != '.')) { 151 //遇到空格符,运算符或者界符 152 break; 153 } else if (err) { 154 token += ch; 155 } else { 156 token += ch; 157 if (ch == '.') { 158 if (flag == 1) { 159 err = true; 160 } else { 161 flag++; 162 } 163 } else if (isalpha(ch)) { 164 err = true; 165 } 166 } 167 } 168 if (token.at(token.length() - 1) == '.') { 169 err = true; 170 } 171 Tokens.emplace_back("INTCON"); 172 vals.push_back(token); 173 if (p != str.length() - 1 || (p == str.length() - 1 && !isdigit(str.at(p)))) { 174 p--; 175 } 176 } 177 void letterCheck(string str) { 178 string token; 179 token.push_back(str.at(p++)); 180 char ch; 181 for (; p < str.length(); p++) { 182 ch = str.at(p); 183 if (!isalnum(ch) && ch != '_') { 184 break; 185 } else { 186 token += ch; 187 } 188 } 189 if (keywords.count(token)) { 190 Tokens.push_back(keywords[token]); 191 vals.push_back(token); 192 } else { 193 Tokens.emplace_back("IDENFR"); 194 vals.push_back(token); 195 } 196 if (p != str.length() - 1 || (p == str.length() - 1 && (!isalnum(str.at(p)) && str.at(p) != '_'))) { 197 p--; 198 } 199 } 200 void stringCheck(string str) { 201 202 string token; 203 token.push_back(str.at(p++)); 204 char ch; 205 for (; p < str.length(); p++) { 206 ch = str.at(p); 207 token += ch; 208 if (ch == '"') { 209 break; 210 } 211 } 212 token.erase(remove(token.begin(),token.end(),'\"'), token.end()); 213 Tokens.emplace_back("STRCON"); 214 vals.emplace_back(token); 215 } 216 void charCheck(string str) { 217 218 string token; 219 token.push_back(str.at(p++)); 220 char ch; 221 for (; p < str.length(); p++) { 222 ch = str.at(p); 223 token += ch; 224 if (ch == '\'') { 225 break; 226 } 227 } 228 token.erase(remove(token.begin(),token.end(),'\''), token.end()); 229 Tokens.emplace_back("CHARCON"); 230 vals.push_back(token); 231 } 232 void symbolCheck(string str) { 233 234 string token; 235 token.push_back(str.at(p++)); 236 char ch; 237 if (symbols.count(token)) { 238 Tokens.push_back(symbols[token]); 239 vals.push_back(token); 240 p--; 241 } else { 242 if (operations.count(token) || token=="!") { 243 if (p < str.length()) { 244 ch = str.at(p); 245 if (operations.count(token + ch)) { 246 token += ch; 247 p++; 248 if (p < str.length()) { 249 ch = str.at(p); 250 if (operations.count(token + ch)) { 251 token += ch; 252 Tokens.push_back(operations[token]); 253 vals.push_back(token); 254 } else { 255 p--; 256 Tokens.push_back(operations[token]); 257 vals.push_back(token); 258 } 259 } else { 260 Tokens.push_back(operations[token]); 261 vals.push_back(token); 262 } 263 } else { 264 p--; 265 Tokens.push_back(operations[token]); 266 vals.push_back(token); 267 } 268 } 269 } else { 270 p--; 271 } 272 } 273 } 274 275 void parsing(){ 276 q = 0; 277 parse1(); //从<程序>节点开始 278 } 279 void parse0() { 280 //<字符串> ::= "{十进制编码为32,33,35-126的ASCII字符}" 281 MatchToken("STRCON"); 282 write<<"<字符串>"<<endl; 283 cout<<"<字符串>"<<endl; 284 } 285 void parse1() { 286 //<程序> ::= [<常量说明>][<变量说明>]{<有返回值函数定义>|<无返回值函数定义>}<主函数> 287 if (Tokens[q] == "CONSTTK") { 288 parse2(); //<常量说明> 289 } 290 if ((Tokens[q] == "INTTK" || Tokens[q] == "CHARTK") && Tokens[q+1] == "IDENFR" && Tokens[q+2] != "LPARENT") { 291 parse7(); //<变量说明> 292 } 293 while ((Tokens[q] == "INTTK" || Tokens[q] == "CHARTK" || Tokens[q] == "VOIDTK") && 294 Tokens[q+1] == "IDENFR" && Tokens[q+2] == "LPARENT") { 295 if (Tokens[q] == "VOIDTK") { 296 parse10(); //<无返回值函数定义> 297 } else { 298 parse9(); //<有返回值函数定义> 299 } 300 } 301 if (Tokens[q] == "VOIDTK" && Tokens[q+1]== "MAINTK") { 302 parse13(); //<主函数> 303 } 304 if (q == Tokens.size()) { 305 cout<<"<程序>"<<endl; 306 write<<"<程序>"<<endl; 307 } 308 } 309 void parse2() { 310 //<常量说明> ::= const<常量定义>;{ const<常量定义>;} 311 do { 312 MatchToken("CONSTTK"); 313 parse3(); //<常量定义> 314 MatchToken("SEMICN"); 315 } while (Tokens[q] == "CONSTTK"); 316 cout<<"<常量说明>"<<endl; 317 write<<"<常量说明>"<<endl; 318 } 319 320 void parse3() { 321 //<常量定义> ::= int<标识符>=<整数>{,<标识符>=<整数>}| char<标识符>=<字符>{,<标识符>=<字符>} 322 if (Tokens[q]== "INTTK") { 323 MatchToken("INTTK"); 324 MatchToken("IDENFR"); 325 MatchToken("ASSIGN"); 326 parse5(); //<整数> 327 while (Tokens[q] == "COMMA") { 328 MatchToken("COMMA"); 329 MatchToken("IDENFR"); 330 MatchToken("ASSIGN"); 331 parse5(); 332 } 333 } 334 if (Tokens[q] == "CHARTK") { 335 MatchToken("CHARTK"); 336 MatchToken("IDENFR"); 337 MatchToken("ASSIGN"); 338 MatchToken("CHARCON"); 339 while (Tokens[q] == "COMMA") { 340 MatchToken("COMMA"); 341 MatchToken("IDENFR"); 342 MatchToken("ASSIGN"); 343 MatchToken("CHARCON"); 344 } 345 } 346 cout<<("<常量定义>")<<endl; 347 write<<("<常量定义>")<<endl; 348 349 } 350 351 void parse4() { 352 //<无符号整数> 353 MatchToken("INTCON"); 354 cout<<("<无符号整数>")<<endl; 355 write<<("<无符号整数>")<<endl; 356 357 } 358 359 void parse5() { 360 //<整数> ::= [+|-]<无符号整数> 361 if (Tokens[q] == "PLUS") 362 MatchToken("PLUS"); 363 else if (Tokens[q] == "MINU") 364 MatchToken("MINU"); 365 parse4(); //<无符号整数> 366 cout<<("<整数>")<<endl; 367 write<<("<整数>")<<endl; 368 369 } 370 371 void parse6() { 372 //<声明头部> ::= int<标识符> |char<标识符> 373 if (Tokens[q] == "INTTK") 374 MatchToken("INTTK"); 375 else if (Tokens[q] == "CHARTK") 376 MatchToken("CHARTK"); 377 MatchToken("IDENFR"); 378 cout<<("<声明头部>")<<endl; 379 write<<("<声明头部>")<<endl; 380 381 } 382 383 void parse7() { 384 //<变量说明> ::= <变量定义>;{<变量定义>;} 385 do { 386 parse8(); //<变量定义> 387 MatchToken("SEMICN"); 388 } while ((Tokens[q] == "INTTK" || Tokens[q] == "CHARTK") && 389 Tokens[q + 1] == "IDENFR" && Tokens[q + 2] != "LPARENT"); 390 cout<<("<变量说明>")<<endl; 391 write<<("<变量说明>")<<endl; 392 393 } 394 void parse8() { 395 //<变量定义> ::= <类型标识符>(<标识符>|<标识符>'['<无符号整数>']'){,(<标识符>|<标识符>'['<无符号整数>']')} 396 if (Tokens[q] == "INTTK") 397 MatchToken("INTTK"); 398 else if (Tokens[q] == "CHARTK") 399 MatchToken("CHARTK"); 400 MatchToken("IDENFR"); 401 if (Tokens[q] == "LBRACK") { 402 MatchToken("LBRACK"); 403 parse4(); //<无符号整数> 404 MatchToken("RBRACK"); 405 } 406 while (Tokens[q] == "COMMA") { 407 MatchToken("COMMA"); 408 MatchToken("IDENFR"); 409 if (Tokens[q] == "LBRACK") { 410 MatchToken("LBRACK"); 411 parse4(); //<无符号整数> 412 MatchToken("RBRACK"); 413 } 414 } 415 cout<<("<变量定义>")<<endl; 416 write<<("<变量定义>")<<endl; 417 418 } 419 void parse9() { 420 //<有返回值函数定义> ::= <声明头部>'('<参数表>')' '{'<复合语句>'}' 421 parse6(); //<声明头部> 422 NVoidFunction.insert({vals[q - 1], 1}); 423 MatchToken("LPARENT"); 424 parse12(); //<参数表> 425 MatchToken("RPARENT"); 426 MatchToken("LBRACE"); 427 parse11(); //<复合语句> 428 MatchToken("RBRACE"); 429 cout<<("<有返回值函数定义>")<<endl; 430 write<<("<有返回值函数定义>")<<endl; 431 432 } 433 void parse10() { 434 //<无返回值函数定义> ::= void<标识符>'('<参数表>')''{'<复合语句>'}' 435 MatchToken("VOIDTK"); 436 MatchToken("IDENFR"); 437 MatchToken("LPARENT"); 438 parse12(); //<参数表> 439 MatchToken("RPARENT"); 440 MatchToken("LBRACE"); 441 parse11(); //<复合语句> 442 MatchToken("RBRACE"); 443 cout<<("<无返回值函数定义>")<<endl; 444 write<<("<无返回值函数定义>")<<endl; 445 446 } 447 void parse11() { 448 //<复合语句> ::= [<常量说明>][<变量说明>]<语句列> 449 if (Tokens[q] == "CONSTTK") { 450 parse2(); //<常量说明> 451 } 452 if ((Tokens[q] == "INTTK" || Tokens[q] == "CHARTK") && 453 Tokens[q + 1]== "IDENFR" && Tokens[q + 2] != "LPARENT") { 454 parse7(); //<变量说明> 455 } 456 parse26(); //<语句列> 457 cout<<("<复合语句>")<<endl; 458 write<<("<复合语句>")<<endl; 459 460 } 461 void parse12() { 462 //<参数表> ::= <类型标识符><标识符>{,<类型标识符><标识符>}| <空> 463 if (Tokens[q] != "RPARENT")//如果下一个token为右小括号,则为空 464 { 465 if (Tokens[q] == "INTTK") 466 MatchToken("INTTK"); 467 else if (Tokens[q] == "CHARTK") 468 MatchToken("CHARTK"); 469 MatchToken("IDENFR"); 470 while (Tokens[q] == "COMMA") { 471 MatchToken("COMMA"); 472 if (Tokens[q] == "INTTK") 473 MatchToken("INTTK"); 474 else if (Tokens[q] == "CHARTK") 475 MatchToken("CHARTK"); 476 MatchToken("IDENFR"); 477 } 478 } 479 cout<<("<参数表>")<<endl; 480 write<<("<参数表>")<<endl; 481 482 } 483 484 void parse13() { 485 //<主函数> ::= void main‘(’‘)’ ‘{’<复合语句>‘}’ 486 MatchToken("VOIDTK"); 487 MatchToken("MAINTK"); 488 MatchToken("LPARENT"); 489 MatchToken("RPARENT"); 490 MatchToken("LBRACE"); 491 parse11(); //<复合语句> 492 MatchToken("RBRACE"); 493 cout<<("<主函数>")<<endl; 494 write<<("<主函数>")<<endl; 495 496 } 497 498 void parse14() { 499 //<表达式> ::= [+|-]<项>{<加法运算符><项>} 500 if (Tokens[q] == "PLUS") 501 MatchToken("PLUS"); 502 else if (Tokens[q] == "MINU") 503 MatchToken("MINU"); 504 parse15(); //<项> 505 while (Tokens[q] == "PLUS" || Tokens[q] == "MINU") { 506 if (Tokens[q] == "PLUS") 507 MatchToken("PLUS"); 508 else if (Tokens[q] == "MINU") 509 MatchToken("MINU"); 510 parse15(); //<项> 511 } 512 cout<<("<表达式>")<<endl; 513 write<<("<表达式>")<<endl; 514 515 } 516 517 void parse15() { 518 //<项> ::= <因子>{<乘法运算符><因子>} 519 parse16(); //<因子> 520 while (Tokens[q] == "MULT" || Tokens[q] == "DIV") { 521 if (Tokens[q] == "MULT") 522 MatchToken("MULT"); 523 else if (Tokens[q] == "DIV") 524 MatchToken("DIV"); 525 parse16(); //<因子> 526 } 527 cout<<("<项>")<<endl; 528 write<<("<项>")<<endl; 529 530 } 531 532 void parse16() { 533 //<因子> ::= <标识符>|<标识符>'['<表达式>']'|'('<表达式>')'|<整数>|<字符>|<有返回值函数调用语句> 534 if (Tokens[q] == "IDENFR") { 535 if (Tokens[q + 1]== "LBRACK") { 536 MatchToken("IDENFR"); 537 MatchToken("LBRACK"); 538 parse14(); //<表达式> 539 MatchToken("RBRACK"); 540 } else if (Tokens[q + 1 ]== "LPARENT") 541 parse234(); //<有返回值函数调用语句> 542 else MatchToken("IDENFR"); 543 } else if (Tokens[q] == "LPARENT") { 544 MatchToken("LPARENT"); 545 parse14(); //<表达式> 546 MatchToken("RPARENT"); 547 } else if (Tokens[q] == "INTCON" || Tokens[q] == "PLUS" || Tokens[q] == "MINU") 548 parse5(); //<整数> 549 else if (Tokens[q] == "CHARCON") 550 MatchToken("CHARCON"); 551 cout<<("<因子>")<<endl; 552 write<<("<因子>")<<endl; 553 554 } 555 556 void parse17() { 557 /*<语句> ::= <条件语句>|<循环语句>| '{'<语句列>'}' 558 | <有返回值函数调用语句>; |<无返回值函数调用语句>;|<赋值语句>; 559 |<读语句>;|<写语句>;|<空>;|<返回语句>;*/ 560 if (Tokens[q] == "IFTK") 561 parse19(); //<条件语句> 562 else if (Tokens[q] == "WHILETK" || Tokens[q] == "DOTK" || Tokens[q] == "FORTK") 563 parse21(); //<循环语句> 564 else if (Tokens[q] == "LBRACE") { 565 MatchToken("LBRACE"); 566 parse26(); //<语句列> 567 MatchToken("RBRACE"); 568 } else if (Tokens[q] == "IDENFR") { 569 if (Tokens[q + 1] == "LPARENT") { 570 parse234(); //<有无返回值函数调用语句> 571 MatchToken("SEMICN"); 572 } else { 573 parse18(); //<赋值语句> 574 MatchToken("SEMICN"); 575 } 576 } else if (Tokens[q] == "SCANFTK") { 577 parse27(); //<读语句> 578 MatchToken("SEMICN"); 579 } else if (Tokens[q] == "PRINTFTK") { 580 parse28(); //<写语句> 581 MatchToken("SEMICN"); 582 } else if (Tokens[q] == "RETURNTK") { 583 parse29(); //<返回语句> 584 MatchToken("SEMICN"); 585 } else if (Tokens[q] == "SEMICN") 586 MatchToken("SEMICN"); 587 cout<<("<语句>")<<endl; 588 write<<("<语句>")<<endl; 589 590 } 591 592 void parse18() { 593 //<赋值语句> ::= <标识符>=<表达式>|<标识符>'['<表达式>']'=<表达式> 594 MatchToken("IDENFR"); 595 if (Tokens[q] == "LBRACK") { 596 MatchToken("LBRACK"); 597 parse14(); //<表达式> 598 MatchToken("RBRACK"); 599 } 600 MatchToken("ASSIGN"); 601 parse14(); //<表达式> 602 cout<<("<赋值语句>")<<endl; 603 write<<("<赋值语句>")<<endl; 604 605 } 606 607 void parse19() { 608 //<条件语句> ::= if '('<条件>')'<语句>[else<语句>] 609 MatchToken("IFTK"); 610 MatchToken("LPARENT"); 611 parse20(); //<条件> 612 MatchToken("RPARENT"); 613 parse17(); //<语句> 614 if (Tokens[q] == "ELSETK") { 615 MatchToken("ELSETK"); 616 parse17(); //<语句> 617 } 618 cout<<("<条件语句>")<<endl; 619 write<<("<条件语句>")<<endl; 620 621 } 622 623 void parse20() { 624 //<条件> ::= <表达式><关系运算符><表达式> //整型表达式之间才能进行关系运算|<表达式> 625 // 表达式为整型,其值为0条件为假,值不为0时条件为真 626 parse14(); //<表达式> 627 if (Tokens[q] == "LSS" || Tokens[q] == "LEQ" || Tokens[q] == "GRE" 628 || Tokens[q] == "GEQ" || Tokens[q] == "EQL" || Tokens[q] == "NEQ") { 629 MatchToken((string) Tokens[q]); 630 parse14(); //<表达式> 631 } 632 cout<<("<条件>")<<endl; 633 write<<("<条件>")<<endl; 634 635 } 636 637 void parse21() { 638 //<循环语句> ::= while '('<条件>')'<语句> 639 // |do<语句>while '('<条件>')' 640 // |for'('<标识符>=<表达式>;<条件>;<标识符>=<标识符>(+|-)<步长>')'<语句> 641 if (Tokens[q] == "WHILETK") { 642 MatchToken("WHILETK"); 643 MatchToken("LPARENT"); 644 parse20(); //<条件> 645 MatchToken("RPARENT"); 646 parse17(); //<语句> 647 } else if (Tokens[q] == "DOTK") { 648 MatchToken("DOTK"); 649 parse17(); //<语句> 650 MatchToken("WHILETK"); 651 MatchToken("LPARENT"); 652 parse20(); //<条件> 653 MatchToken("RPARENT"); 654 } else if (Tokens[q] == "FORTK") { 655 MatchToken("FORTK"); 656 MatchToken("LPARENT"); 657 MatchToken("IDENFR"); 658 MatchToken("ASSIGN"); 659 parse14(); //<表达式> 660 MatchToken("SEMICN"); 661 parse20(); //<条件> 662 MatchToken("SEMICN"); 663 MatchToken("IDENFR"); 664 MatchToken("ASSIGN"); 665 MatchToken("IDENFR"); 666 if (Tokens[q] == "PLUS") 667 MatchToken("PLUS"); 668 else if (Tokens[q] == "MINU") 669 MatchToken("MINU"); 670 parse22(); //<步长> 671 MatchToken("RPARENT"); 672 parse17(); //<语句> 673 } 674 cout<<("<循环语句>")<<endl; 675 write<<("<循环语句>")<<endl; 676 677 } 678 679 void parse22() { 680 //<步长>::= <无符号整数> 681 parse4(); //<无符号整数> 682 cout<<("<步长>")<<endl; 683 write<<("<步长>")<<endl; 684 685 } 686 687 void parse234() { 688 //<有无返回值函数调用语句> ::= <标识符>'('<值参数表>')' 689 int FunctionType = 0; 690 if(NVoidFunction.count(vals[q])) { 691 FunctionType = NVoidFunction[vals[q]]; 692 } 693 MatchToken("IDENFR"); 694 MatchToken("LPARENT"); 695 parse25(); //<值参数表> 696 MatchToken("RPARENT"); 697 if (FunctionType == 1) { 698 cout<<("<有返回值函数调用语句>")<<endl; 699 write<<("<有返回值函数调用语句>")<<endl; 700 701 } else { 702 cout<<("<无返回值函数调用语句>")<<endl; 703 write<<("<无返回值函数调用语句>")<<endl; 704 705 } 706 } 707 708 void parse25() { 709 //<值参数表> ::= <表达式>{,<表达式>}|<空> 710 if (Tokens[q] != "RPARENT") { 711 parse14(); //<表达式> 712 while (Tokens[q] == "COMMA") { 713 MatchToken("COMMA"); 714 parse14(); 715 } 716 } 717 cout<<("<值参数表>")<<endl; 718 write<<("<值参数表>")<<endl; 719 720 } 721 722 void parse26() { 723 //<语句列> ::= {<语句>} 724 while (Tokens[q] != "RBRACE") 725 parse17(); //<语句> 726 cout<<("<语句列>")<<endl; 727 write<<("<语句列>")<<endl; 728 729 } 730 731 void parse27() { 732 //<读语句> ::= scanf '('<标识符>{,<标识符>}')' 733 MatchToken("SCANFTK"); 734 MatchToken("LPARENT"); 735 MatchToken("IDENFR"); 736 while (Tokens[q] == "COMMA") { 737 MatchToken("COMMA"); 738 MatchToken("IDENFR"); 739 } 740 MatchToken("RPARENT"); 741 cout<<("<读语句>")<<endl; 742 write<<("<读语句>")<<endl; 743 744 } 745 746 void parse28() { 747 //<写语句> ::= printf '(' <字符串>,<表达式> ')' 748 // | printf '('<字符串> ')' 749 // | printf '('<表达式>')' 750 MatchToken("PRINTFTK"); 751 MatchToken("LPARENT"); 752 if (Tokens[q] == "STRCON") 753 parse0(); //<字符串> 754 else 755 parse14(); //<表达式> 756 if (Tokens[q] == "COMMA") { 757 MatchToken("COMMA"); 758 parse14(); //<表达式> 759 } 760 MatchToken("RPARENT"); 761 cout<<("<写语句>")<<endl; 762 write<<("<写语句>")<<endl; 763 764 } 765 766 void parse29() { 767 //<返回语句> ::= return['('<表达式>')'] 768 MatchToken("RETURNTK"); 769 if (Tokens[q] == "LPARENT") { 770 MatchToken("LPARENT"); 771 parse14(); //<表达式> 772 MatchToken("RPARENT"); 773 } 774 cout<<("<返回语句>")<<endl; 775 write<<("<返回语句>")<<endl; 776 777 } 778 779 void MatchToken(string expected) { 780 if (Tokens[q] == expected) { 781 cout<<Tokens[q]<<" "<<vals[q]<<endl; 782 write<<Tokens[q]<<" "<<vals[q]<<endl; 783 q++; //下一个单词 784 } 785 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 上周热点回顾(3.3-3.9)
· AI 智能体引爆开源社区「GitHub 热点速览」