public void Insert(TreeNode pNode) { // pNode.nodekind must be funK, // pNode.name must be not in FunDecListRec; FunDecListRec temp = new FunDecListRec(pNode.Name, pNode.Type); // count the params TreeNode p = pNode.Child[0]; // params link in pNode.chilld[0].sibling temp.lineno = pNode.LineNum;// record functions' line if (p != null) { temp.Params = new ParamListRec(p.Type, p.IsArray); temp.count++; ParamListRec l = temp.Params; while (p.Sibling != null) { p = p.Sibling; l.next = new ParamListRec(p.Type, p.IsArray); l = l.next; temp.count++; } } if (first == null) // has not function declarations in list { first = last = temp; } else { last.next = temp; last = last.next; } }
/// <summary> /// 构造函数,传入词法的tokenlist /// </summary> /// <param name="tokenList"></param> public Parser(List<Token> ttokenList) { _good = false; this.tokenList = ttokenList; root = null; currentTokenIndex = -1; }
/// <summary> /// 递归生成语法树,节点的名字从0开始编号,显示的内容不是这些数字 /// </summary> /// <param name="TN"></param> /// <param name="FatherNode"></param> private void BuildingTree(TreeNode TN, TreeContainer.TreeNode CurrentNode, TreeContainer.TreeNode FatherNode) { TreeContainer.TreeNode temp, tempFatherNode; //生成所有的孩子节点 for (int i = 0; i < 4; ++i) { if (TN.Child[i] == null) { continue; } temp = CreaterTreeNode(TN.Child[i]); temp = Tree.AddNode(temp, CurrentNode); tempFatherNode = CurrentNode; BuildingTree(TN.Child[i], temp, tempFatherNode); } //生成兄弟节点 TreeNode tempTN = TN; //开始用while,错了,改成if。 if (tempTN.Sibling != null) { tempTN = tempTN.Sibling; temp = CreaterTreeNode(tempTN); temp = Tree.AddNode(temp, FatherNode); BuildingTree(tempTN, temp, FatherNode); } }
/// <summary> /// 产生语法树,传入虚拟根节点,由他扩展。 /// </summary> /// <param name="vitualRoot"></param> public void CreatSyntaxTree(TreeNode vitualRoot) { TreeContainer.TreeNode treeRoot; //命名树节点 treeRoot = CreaterTreeNode(vitualRoot); treeRoot = Tree.AddRoot(treeRoot); BuildingTree(vitualRoot, treeRoot, null); }
/// <summary> /// build parse tree /// </summary> public TreeNode BuildSyntaxTree() { root = new TreeNode(NodeKind.proK, TokenType.NONE , "Root", 0, "global"); TreeNode p = null; scope = "global"; p = root.Child[0] = Program(); if (p != null) p.Father = root; // while (p != null && p.Sibling != null) { p = p.Sibling; p.Father = root; } return root; }
/// <summary> /// check if a function call's argument match its declaration parameters; /// return -1, not found; /// return -2, type not match; /// return -3, match; /// else return delcaration parameter count, not match, and /// "string &args" is the function's parament list, like "int, int[], int" /// line to record the functions' lineno that its defined here. /// </summary> public int Check(TreeNode pNode, string args,ref int line) { FunDecListRec l = first; while ((l!=null) && l.name != pNode.Name) l = l.next; if (l==null) return -1; // function use before its declaration or not declara ParamListRec p = l.Params; TreeNode t = pNode.Child[0]; // record paraments list, this is not a good idea while (p!=null) { if (p.type == TokenType.VOID) args = "void, " + args; else if (p.type == TokenType.INT){ args = (p.isArr ? "int[], " : "int, ") + args; } p = p.next; } // args.erase(args.Length-2); // erase last ", " args = args.Remove(args.Length - 2,1); line = l.lineno; // set it point to l.params after record paraments list p = l.Params; while (p!=null &&t!=null) { if ((p.type == t.Type && p.isArr == t.IsArray) || (t.NodeKind ==NodeKind.expK && t.exp ==ExpKind.ConstK && t.Type == TokenType.NUMBER)) { p = p.next; t = t.Sibling ; } else { return -2; // type not match; } } if (p!=null || t!=null) { return l.count; // params count not match } else return -3; // all match; }
public Analyzer(List<Token> tokenlist) { traceAnalyze= true; traceParse = true; parse = new Parser(tokenlist); program = null; program = parse.BuildSyntaxTree(); program = program.Child[0]; // symbolTab.initial(); // because symbolTab and FunArgs is static member, // FunArgs.initial(); // so, before use , should reset/initial them //symFile = filename; //int pos = symFile.rfind('.'); //symFile.erase(pos, symFile.length()-1); //symFile += ".tab"; // symbol table file is_good_ = true; location = 0; // intial memory location err = 0; // there are static member, should initial before use warn = 0; }
public void traverse1(TreeNode t) { if (t != null) { InsertNode(t); for (int i = 0; i <= 10; ++i) { traverse1( t.Child[i]); } // postProc(t); traverse1( t.Sibling); } }
/// <summary> /// /// </summary> /// <param name="pNode"></param> void CheckNode(TreeNode pNode) { TreeNode t; string args; int ret, oldline; // record the return value and function defined lineno if its defined. // initial them ret = oldline = -1; args = ""; t = pNode; switch (t.NodeKind) { //case NodeKind.stmtK: case NodeKind.stmtK: switch (t.stmt) { case StmtKind.readK: if (t.Child[0] != null) { t.Type = t.Child[0].Type; if (t.Type != TokenType.INT){ //outputMsg(t.lineno, "read statement can only read a \"int\" value to a int variable!"); err++; } } else { err++; ErrorRecord(AnalyzerErrorType.MaybeCompilerBug,t); //outputMsg(-1, "maybe compiler bug!"); } break; case StmtKind.writeK: if (t.Child[0] != null) { t.Type = t.Child[0].Type; if (t.Type != TokenType.INT) { //outputMsg(t.lineno, "write statement can only output a \"int\" variable or a number output!"); err++; } } else { err++; ErrorRecord(AnalyzerErrorType.MaybeCompilerBug, t); //outputMsg(-1, "maybe compiler bug!"); } break; case StmtKind.returnK: if (t.Child[0] == null) { // return should be a void if (symbolTab.SearchType(t.Name, "global") != TokenType.VOID) { //sprintf(msg_temp, " function \"int %s(...)\" must have return value ", t.Name.c_str()); //outputMsg(t.lineno, msg_temp); err++; } } break; case StmtKind.callK: ret = FunArgs.Check(t, args, ref oldline); if (ret != -3) // -3 is ok { err++; warn++; if (ret >= 0) { //sprintf(msg_temp, // "too few or many paramenters to call function \"%s(%s)\", its has %d params", // t.Name.c_str(), // args.c_str(), // ret); //outputMsg(t.lineno, msg_temp); // out put the functions' declaration, //sprintf(msg_temp, // "see the function \"%s(%s)\" declaration here!!", // t.Name.c_str(), // args.c_str()); //outputMsg(oldline, msg_temp); } else if (ret == -1) { //sprintf(msg_temp, "function \"%s\"(...) has not declared before use it", t.Name.c_str()); //outputMsg(t.lineno, msg_temp); } else { //sprintf(msg_temp, // " call function \"%s(%s)\" with no matched Type paramenters!", // t.Name.c_str(), args.c_str()); //outputMsg(t.lineno, msg_temp); //sprintf(msg_temp, // "see the function \"%s(%s)\" declaration here!!", // t.Name.c_str(), // args.c_str()); //outputMsg(oldline, msg_temp); } } else { t.Type = symbolTab.SearchType(t.Name, t.Scope); } break; default: break; } break; case NodeKind.expK: switch (t.exp) { case ExpKind.OpK: if (Convert.ToInt32(t.Type) == Convert.ToInt32('=')) { t.Type = t.Child[0].Type; } else { if (t.Child[0].Type == TokenType.VOID || t.Child[1].Type == TokenType.VOID) { err++; //outputMsg(t.lineno, "illegal use of Type \"void\""); } else if (t.Child[0].Type == TokenType.INT || t.Child[1].Type == TokenType.INT) { t.Type = TokenType.INT; } else { // ... } } break; case ExpKind.IDK: t.Type = symbolTab.SearchType(t.Name, t.Scope); t.IsArray = symbolTab.SearchArray(t.Name, t.Scope); break; default: break; } break; default: break; } }
/// <summary> /// 27. call → ID ( args ) /// </summary> /// <returns></returns> private TreeNode Call() { Word iToken = idNameToken as Word; TreeNode p = new TreeNode(StmtKind.callK, iToken.Lexeme, currentToken.LineNumber, scope); TreeNode temp = null; p.Scope = "global"; p.Child[0] = Args(); if (p.Child[0] != null) { p.Child[0].Father = p; } temp = p.Child[0]; while (temp != null && temp.Sibling != null) { temp = temp.Sibling; temp.Father = p; } if (!Match(')')) { //错误处理 ErrorRecord(ParseErrorType.MissingRParenthesis); --currentTokenIndex; } return p; }
public void InsertNode(TreeNode t) { if (t == null) return; switch (t.NodeKind ) { case NodeKind.funK: if (symbolTab.LookUp(t.Name, t.Scope) == -1) { symbolTab.Insert(t.Name, t.Scope, t.Type, t.LineNum, location, false); ////addMemLoc(); FunArgs.Insert(t); } else { //Analyzer::parse.add_err(); err++; // //sprintf(msg_temp, "function \"%s\"(...) redefinition", t.Name.c_str()); ////outputMsg(t.LineNum, msg_temp); } break; case NodeKind.varK: case NodeKind.paramK: if (symbolTab.LookUp(t.Name, t.Scope) == -1) { symbolTab.Insert(t.Name, t.Scope, t.Type, t.LineNum, location, t.IsArray); ////addMemLoc(); } else { err++; //sprintf(msg_temp, "variable \"%s\" redefinition", t.Name.c_str()); ErrorRecord(AnalyzerErrorType.VariableRedefinition, t); //outputMsg(t.LineNum, msg_temp); } break; case NodeKind.stmtK: // just call if (t.stmt == StmtKind.callK) { if (symbolTab.LookUp(t.Name, t.Scope) == -1) { err++; //sprintf(msg_temp, "unresolved external symbol \"%s\"", t.Name.c_str()); //outputMsg(t.LineNum, msg_temp); } else { symbolTab.Insert(t.Name, t.Scope, TokenType.ID, t.LineNum, 0, false); } } break; case NodeKind.expK: if (t.exp == ExpKind.IDK) { if ( symbolTab.LookUp(t.Name, t.Scope) == -1 && symbolTab.LookUp(t.Name, "global") == -1) { // undeclared //Analyzer::parse.add_err(); err++; ErrorRecord(AnalyzerErrorType.IdentifierUndeclared, t); //sprintf(msg_temp, "undeclared identifier: \"%s\"", t.Name.c_str()); //outputMsg(t.LineNum, msg_temp); } else if (symbolTab.LookUp(t.Name, t.Scope) != -1) { // local variable if ((t.Father!=null) && (t.Father.NodeKind != NodeKind.stmtK || t.Father.stmt != StmtKind.callK)/* not in call statement */ && t.IsArray != symbolTab.SearchArray(t.Name,t.Scope)) { //Analyzer::parse.add_err(); err++; //sprintf(msg_temp, "\"%s\" is %s declared as array", t.Name.c_str(), t.bArr? "not" : ""); //outputMsg(t.LineNum, msg_temp); } else { symbolTab.Insert(t.Name, t.Scope, t.Type, t.LineNum, 0, false); } } else { // global variable t.Scope = "global"; if ((t.Father != null) && (t.Father.NodeKind != NodeKind.stmtK || t.Father.stmt != StmtKind.callK)/* not in call statement */ && t.IsArray != symbolTab.SearchArray(t.Name, t.Scope)) { //Analyzer::parse.add_err(); err++; //sprintf(msg_temp, "\"%s\" is %s declared as array", t.Name.c_str(), t.bArr? "not" : ""); //outputMsg(t.LineNum, msg_temp); } else { symbolTab.Insert(t.Name, t.Scope, t.Type, t.LineNum, 0, false); } } } break; default: break; } }
/// <summary> /// Type checking by a postorder syntax tree traversal /// </summary> /// <param name="pNode"></param> void TypeCheck(TreeNode pNode) { Traverse2(pNode); if ( symbolTab.LookUp("main", "global") == -1) { err++; is_good_ = false; ////outputMsg(-1, "Unresolved external symbol _main"); warn++; ////outputMsg(-1, "program must have function \"main(void)\" !"); } }
/// <summary> /// 4. var-declaration → type-specifier ID(,...); | type-specifier ID [ NUM ](,...); /// 5. type-specifier → int | void /// </summary> /// <returns></returns> TreeNode VarDeclaration() { // now, cToken.str == ";", "," or "[" Word iToken = idNameToken as Word; TreeNode temp = new TreeNode(NodeKind.varK, (TokenType)typeToken.TokenTypes, iToken.Lexeme, currentToken.LineNumber, scope); if (CheckCurrentToken('[')) { currentToken = GetNextToken();//must NUMber if (!CheckCurrentToken(TokenType.NUMBER)) { ErrorRecord(ParseErrorType.MissingArraySize); ConsumeUntil(";", "}"); //error /*scan->add_err(); sprintf(msg_temp, "Syntax error: missing array size in declaration of array %s[]", iToken.str.c_str()); outputMsg(scan->lineno(), msg_temp); delete temp; consumeUntil(SEMI, RBRACE); // error recovery in global declaration return NULL;*/ return null; } temp.IsArray = true; Number num = currentToken as Number; temp.ArraySize = Convert.ToInt32(num.Lexeme); if (!Match(Convert.ToInt32(']'))) { ErrorRecord(ParseErrorType.MissingRBracketInArray); --currentTokenIndex; // need ']' /* scan->add_err(); sprintf(msg_temp, "Syntax error: missing \']\' in declaration of array %s[]", iToken.str.c_str()); scan->push(); */ } currentToken = GetNextToken();// ";" or "," } if (CheckCurrentToken(',')) { idNameToken = currentToken = GetNextToken();//next id if (idNameToken.TokenTypes != Convert.ToInt32( TokenType.ID)) { //错误处理 ErrorRecord(ParseErrorType.ReservedToken); ConsumeUntil(";", "}"); return temp; } currentToken = GetNextToken();//expected ";", ",", "[" if (CheckCurrentToken(';')|| CheckCurrentToken(',') || CheckCurrentToken('[')) { temp.Sibling = VarDeclaration(); } else { //错误处理 ErrorRecord(ParseErrorType.MissingSemi); --currentTokenIndex; return temp; } } else if ( !CheckCurrentToken(';')) { //错误处理 ErrorRecord(ParseErrorType.MissingSemiAfterDeclarationSequence); ConsumeUntil(";", "}"); } return temp; }
/// <summary> /// 30. read → read( int ); /// </summary> /// <returns></returns> TreeNode ReadStmt() { // currentToken.str == "read" TreeNode temp = null; if (!Match('(')) { ErrorRecord(ParseErrorType.MissingLParenthesis); ConsumeUntil(";","}"); //scan->add_err(); //outputMsg(scan->lineno(), "Syntax error: missing \'(\'"); //consumeUntil(SEMI, RBRACE); return null; } idNameToken = currentToken = GetNextToken(); if (!CheckCurrentToken(TokenType.ID)) { //错误处理 ErrorRecord(ParseErrorType.BadArgument); ConsumeUntil(";", "}"); return null; } temp = new TreeNode(StmtKind.readK, "read", currentToken.LineNumber, scope); if ((temp.Child[0] = Var()) != null) { temp.Child[0].Father = temp; } if (!Match(')')) { ErrorRecord(ParseErrorType.MissingRParenthesis); ConsumeUntil(";", "}"); //scan->add_err(); //outputMsg(scan->lineno(), "Syntax error: missing \')\'"); //consumeUntil(SEMI, RBRACE); return temp; } if (!Match(';')) { ErrorRecord(ParseErrorType.MissingSemiOnly); --currentTokenIndex; //scan->add_err(); //outputMsg(scan->lineno(), "Syntax error: missing \';\'"); //scan->push(); } return temp; }
/// <summary> /// 生成一个显示树的节点,给它付名字(0开始变化的数字),和内容 /// </summary> /// <param name="LogicalTreeNode"></param> /// <returns></returns> private TreeContainer.TreeNode CreaterTreeNode(TreeNode LogicalTreeNode) { ++treeNodeCount; TreeContainer.TreeNode tempTreeNode = new TreeContainer.TreeNode(); TextBlock NodeName = new TextBlock(); NodeName.Width = 75; NodeName.Height = 30; NodeName.TextWrapping = TextWrapping.Wrap; NodeName.FontSize = 18; NodeName.FontWeight = FontWeights.Bold; NodeName.TextAlignment = TextAlignment.Center; NodeName.FontFamily = new FontFamily("Comic Sans MS"); NodeName.Text = LogicalTreeNode.Name; ToolTip toolTip = new ToolTip(); SyntaxTreeNodeToolTip toolTipContent = new SyntaxTreeNodeToolTip(); String NodeKindName = ""; switch (LogicalTreeNode.NodeKind) { case NodeKind.proK: NodeKindName = "Program"; break; case NodeKind.funK: NodeKindName = "Function declaration"; break; case NodeKind.paramK: NodeKindName = "Parameter"; break; case NodeKind.varK: NodeKindName = "Variable declaration"; break; case NodeKind.stmtK: switch ((StmtKind)LogicalTreeNode.Kind) { case StmtKind.ifK: NodeKindName = "If"; break; case StmtKind.readK: NodeKindName = "Call"; break; case StmtKind.writeK: NodeKindName = "Call"; break; case StmtKind.returnK: NodeKindName = "Return"; break; case StmtKind.callK: NodeKindName = "Call"; break; } break; case NodeKind.expK: switch ((ExpKind)LogicalTreeNode.Kind) { case ExpKind.ConstK: NodeKindName = "const"; break; case ExpKind.IDK: NodeKindName = "ID"; break; case ExpKind.OpK: NodeKindName = "Operater"; break; } break; } toolTipContent.NodeKindContent.Text = NodeKindName; toolTipContent.ScopeContent.Text = LogicalTreeNode.Scope; String TypeName =""; if(Convert.ToInt16(LogicalTreeNode.Type)<=255) TypeName = ((char)(Convert.ToInt16(LogicalTreeNode.Type))).ToString(); else { switch(Convert.ToInt16(LogicalTreeNode.Type)) { case 256: TypeName = "ELSE"; break; case 257: TypeName = "EQUAL"; break; case 258: TypeName = "GREATERQUAL"; break; case 259: TypeName = "ID"; break; case 260: TypeName = "IF"; break; case 261: TypeName = "INT"; break; case 262: TypeName = "LEFTCOMMON"; break; case 263: TypeName = "LESSEQUAL"; break; case 264: TypeName = "MINUS"; break; case 265: TypeName = "NOTEQUAL"; break; case 266: TypeName = "NUMBER"; break; case 267: TypeName = "RETURN"; break; case 268: TypeName = "RIGHTCOMMON"; break; case 269: TypeName = "WHILE"; break; case 270: TypeName = "VOID"; break; case 271: TypeName = "EOF"; break; case 272: TypeName = "NONE"; break; case 273: TypeName = "READ"; break; case 274: TypeName = "WRITE"; break; } } toolTipContent.TypeContent.Text = TypeName; toolTipContent.IsArrayConent.Text = LogicalTreeNode.IsArray.ToString(); toolTipContent.ArraySizeContent.Text = LogicalTreeNode.ArraySize.ToString(); toolTipContent.LineNumberContent.Text = LogicalTreeNode.LineNum.ToString(); toolTip.Background = Brushes.Transparent; toolTip.BorderThickness = new Thickness(0); toolTip.Content = toolTipContent; NodeName.ToolTip = toolTip; tempTreeNode.Content = NodeName; tempTreeNode.Name = "node" + treeNodeCount.ToString(); return tempTreeNode; }
/// <summary> /// 31. write → write( int ); /// </summary> /// <returns></returns> TreeNode WriteStmt() { TreeNode temp = null; if (!Match('(')) { ErrorRecord(ParseErrorType.MissingRParenthesis); ConsumeUntil(";", "}"); //scan->add_err(); //outputMsg(scan->lineno(), "Syntax error: missing \'(\'"); //consumeUntil(SEMI, RBRACE); return null; } temp = new TreeNode(StmtKind.writeK, "write", currentToken.LineNumber, scope); currentToken = GetNextToken(); if ((temp.Child[0] = Expression()) != null) { temp.Child[0].Father = temp; } if (!Match(')')) { ErrorRecord(ParseErrorType.MissingRParenthesis); ConsumeUntil(";", "}"); //scan->add_err(); //outputMsg(scan->lineno(), "Syntax error: missing \')\'"); //consumeUntil(SEMI, RBRACE); return temp; } if (!Match(';')) { ErrorRecord(ParseErrorType.MissingSemiOnly); --currentTokenIndex; //scan->add_err(); //outputMsg(scan->lineno(), "Syntax error: missing \';\'"); //scan->push(); } return temp; }
/// <summary> /// 7. params → params-list | void /// 8. param-list→ param-list, param | param /// 9. param→ type-specifier ID | type-specifier ID [ ] /// </summary> /// <returns></returns> TreeNode Params() { TreeNode first = null; TreeNode temp = null; typeToken = currentToken = GetNextToken(); if (CheckCurrentToken(')')) { --currentTokenIndex;//scan->push(); return temp;//null } if (typeToken.TokenTypes == Convert.ToInt32(TokenType.VOID)) { if (Match(Convert.ToInt32( ')'))) { --currentTokenIndex; return temp; // NULL } else { --currentTokenIndex;//scan->push(); // not ")" } } while (typeToken.TokenTypes == Convert.ToInt32(TokenType.INT) || typeToken.TokenTypes == Convert.ToInt32(TokenType.VOID)) { idNameToken = currentToken = GetNextToken(); if (idNameToken.TokenTypes != Convert.ToInt32(TokenType.ID)) { //error ErrorRecord(ParseErrorType.InvalidParameter); } else { Word iToken = idNameToken as Word; temp = new TreeNode(NodeKind.paramK, (TokenType)typeToken.TokenTypes, iToken.Lexeme, currentToken.LineNumber, scope); temp.Sibling = first; first = temp; } currentToken = GetNextToken(); if (CheckCurrentToken('[')) { temp.IsArray = true; if (!Match(Convert.ToInt32(']'))) { //错误处理 ErrorRecord(ParseErrorType.MissingArrayParameter); ConsumeUntil(";", ")"); } else { currentToken = GetNextToken();//',' } } if (CheckCurrentToken(')')) {//')' break;//')' } else if (CheckCurrentToken(','))//',' { typeToken = currentToken = GetNextToken(); } else { break; } } --currentTokenIndex; //next is ')' return first; }
/// <summary> /// 15. selection-stmt → if (expression ) s tatement /// | if ( expression ) statement else statement /// </summary> /// <returns></returns> TreeNode IfStmt() { Word CToken = currentToken as Word; TreeNode temp = new TreeNode(StmtKind.ifK,CToken.Lexeme,currentToken.LineNumber,scope); TreeNode p = null; if (!Match('(')) { // if ( //错误处理 ErrorRecord(ParseErrorType.MissingLParenthesisInIf); //scan->add_err(); //outputMsg(scan->lineno(), "Syntax error: missing \'(\' in \"if\" statement"); } else { currentToken = GetNextToken(); } temp.Child[0] = Expression(); if (temp.Child[0] != null) temp.Child[0].Father = temp; if (!Match(')')) { //错误处理 ErrorRecord(ParseErrorType.MissingRParenthesisInIf); } p = temp.Child[1] = CompoundStmt(); if (p != null) p.Father = temp; while (p != null && p.Sibling != null) { p = p.Sibling; p.Father = temp; } currentToken = GetNextToken(); if (CheckCurrentToken(TokenType.ELSE)) { p = temp.Child[2] = CompoundStmt(); if (p != null) p.Father = temp; while (p!=null && p.Sibling!=null) { p = p.Sibling; p.Father = temp; } } else { // if has no 'else' statement, push the next token back --currentTokenIndex; } return temp; }
/// <summary> /// 6. fun-declaration → type-specifier ID ( params ) compound-stmt /// </summary> /// <returns></returns> TreeNode FunDeclaration() { Word iToken = idNameToken as Word; TreeNode temp = new TreeNode(NodeKind.funK, (TokenType)typeToken.TokenTypes, iToken.Lexeme, currentToken.LineNumber, scope); TreeNode p = null; scope = iToken.Lexeme; p = temp.Child[0] = Params(); if (p != null) p.Father = temp; // while (p != null && p.Sibling != null) { p = p.Sibling; p.Father = temp; } //scan->push(); //--currentTokenIndex;//调了N久 if (!Match(Convert.ToInt32(')'))) { ErrorRecord(ParseErrorType.MissingRParenthesisInFunction); --currentTokenIndex; //error //scan->add_err(); //sprintf(msg_temp, // "Syntax error: missing \')\' in function %s(...) declaration", // iToken.str.c_str()); //outputMsg(scan->lineno(), msg_temp); //scan->push(); } // compound statements p = temp.Child[1] = CompoundStmt(); if (p != null) p.Father = temp; while (p != null && p.Sibling!=null) { p = p.Sibling; p.Father = temp; } return temp; }
/// <summary> /// 26. factor → ( expression ) | var | call | NUM /// </summary> /// <returns></returns> private TreeNode Factor() { TreeNode temp = null; switch (currentToken.TokenTypes) { case (Int32)TokenType.NUMBER: Number NToken = currentToken as Number; temp = new TreeNode(ExpKind.ConstK, (TokenType)currentToken.TokenTypes, NToken.Lexeme , currentToken.LineNumber, scope); break; case (Int32)TokenType.ID: idNameToken = currentToken; currentToken = GetNextToken(); if (CheckCurrentToken('(')) temp = Call(); else { --currentTokenIndex; temp = Var(); } break; case (Int32)('('): currentToken = GetNextToken(); temp = Expression(); if (!Match(')')) { ErrorRecord(ParseErrorType.MissingRParenthesis); --currentTokenIndex; //scan->add_err(); //outputMsg(scan->lineno(), "Syntax Error: missing \')\'"); //scan->push(); } break; default: ErrorRecord(ParseErrorType.ExpressionIsUnexpected); ConsumeUntil(";", "}"); //scan->add_err(); //sprintf(msg_temp, "Syntax error: \'%s\' expression is unexpected!", cToken.str.c_str()); //outputMsg(scan->lineno(), msg_temp); //consumeUntil(SEMI, RBRACE); break; } return temp; }
private void ErrorRecord(AnalyzerErrorType analyzerErrorType,TreeNode t) { ErrorBase.ErrorManager.AddAnalyzerError(new AnalyzerError( analyzerErrorType,t.LineNum, 0, t.Name) ); }
/// <summary> /// 16. iteration-stmt → while ( expression ) statement /// </summary> /// <returns></returns> TreeNode WhileStmt() { Word CToken = currentToken as Word; TreeNode temp = new TreeNode(StmtKind.whileK,CToken.Lexeme,currentToken.LineNumber,scope); TreeNode p = null; if (!Match('(')) { ErrorRecord(ParseErrorType.MissingLParenthesisInWhile); /* // while ( scan->add_err(); // add error count, // out put the error message outputMsg(scan->lineno(), "Syntax error: missing \'(\' in \"while\" statement"); */ } else { currentToken = GetNextToken(); } // cToken should be the first token of expression now ... temp.Child[0] = Expression(); if (temp.Child[0] != null) temp.Child[0].Father = temp; if (!Match(')')) { //while() //错误处理 ErrorRecord(ParseErrorType.MissingRParenthesisInWhile); } p = temp.Child[1] = CompoundStmt(); if (p != null) p.Father = temp; while (p != null && p.Sibling != null) { p = p.Sibling; p.Father = temp; } return temp; }
void Traverse2(TreeNode t) { if (t != null) { for (int i = 0; i < t.Child.Length; ++i) { if (t.Child != null) Traverse2( t.Child[i]); } CheckNode(t); Traverse2( t.Sibling); } }
/// <summary> /// 24. term → term mulop factor | factor /// 25. mulop →* | / /// </summary> /// <returns></returns> private TreeNode Term() { TreeNode p = Factor(); currentToken = GetNextToken(); while (CheckCurrentToken('*') || CheckCurrentToken('/') || CheckCurrentToken('%')) { TreeNode temp = new TreeNode(ExpKind.OpK, (TokenType)currentToken.TokenTypes, currentToken.TokenInfo, currentToken.LineNumber, scope); temp.Child[0] = p; p = temp; if (p.Child[0] != null) p.Child[0].Father = p; currentToken = GetNextToken(); p.Child[1] = Factor(); if (p.Child[1] != null) { p.Child[1].Father = p; } currentToken = GetNextToken(); } --currentTokenIndex; return p; }
/// <summary> /// constructs the symbol table by preorder traversal of the syntax tree /// </summary> /// <param name="pNode"></param> public void BuildSymbolTable(TreeNode pNode) { traverse1(pNode); }
/// <summary> /// 19. var → ID | ID [ expression ] /// </summary> /// <returns></returns> TreeNode Var() { Word iToken = idNameToken as Word; TreeNode temp = new TreeNode(ExpKind.IDK, (TokenType)currentToken.TokenTypes, iToken.Lexeme, currentToken.LineNumber, scope); // "[" currentToken = GetNextToken(); if (CheckCurrentToken('[')) { temp.IsArray = true; currentToken = GetNextToken(); temp.Child[0] = Expression(); if (!Match(']')) { ErrorRecord(ParseErrorType.MissingRBracket); --currentTokenIndex; //scan->add_err(); //outputMsg(scan->lineno(), "Syntax error: missing \']\'"); //scan->push(); } //改动,不把数组的大小变成一个单独的节点。 temp.ArraySize = Convert.ToInt16(temp.Child[0].Name.ToString()); temp.Child[0] = null; } else { --currentTokenIndex; } return temp; }
/// <summary> /// 17. return-stmt → return; | return expression; /// </summary> /// <returns></returns> TreeNode ReturnStmt() { // cToken.str == "return" Word NToken = currentToken as Word; TreeNode temp = new TreeNode(StmtKind.returnK, NToken.Lexeme, currentToken.LineNumber, scope); currentToken = GetNextToken(); //TreeNode temp11 = new TreeNode(StmtKind.returnK, NToken.Lexeme, currentToken.LineNumber, scope); //TreeNode temp1 = new TreeNode(StmtKind.returnK, NToken.Lexeme, currentToken.LineNumber, scope); if (!CheckCurrentToken(';')) { temp.Child[0] = Expression(); if (!Match(';')) { //错误处理 ErrorRecord(ParseErrorType.MissingSemiInReturn); --currentTokenIndex; } } return temp; }
/// <summary> /// 18. expression → var = expression | simple-expression /// </summary> /// <returns></returns> private TreeNode Expression() { // cToken == (, k_ID, k_NUM TreeNode temp = SimpleExpression(); TreeNode p = temp; currentToken = GetNextToken(); if (CheckCurrentToken('=')) { if (temp.Type != TokenType.ID && (Int32)temp.Type != (Int32)('=')) { //错误处理 ErrorRecord(ParseErrorType.LeftID); ConsumeUntil(";", ")"); return null; } p = new TreeNode(ExpKind.OpK, (TokenType)currentToken.TokenTypes, currentToken.TokenInfo, currentToken.LineNumber, scope); p.Child[0] = temp; if (p.Child[0] != null) p.Child[0].Father = p; currentToken = GetNextToken(); p.Child[1] = Expression(); if (p.Child[1] != null) p.Child[1].Father = p; } else { --currentTokenIndex; } return p; }
private void SyntaxAnalysis(object sender, ExecutedRoutedEventArgs e) { LexicalAnalysis(sender, e); Parser parser = new Parser(tokenlist); root = parser.BuildSyntaxTree(); if (ErrorManager.ErrorList.Count == 0) { error.Visibility = Visibility.Collapsed; SyntaxTree syntaxTree = new SyntaxTree(); syntaxTree.CreatSyntaxTree(root); syntaxTree.Show(); } else { error.Visibility = Visibility.Visible; dg.Visibility = Visibility.Collapsed; error.ItemsSource = null; error.ItemsSource = ErrorManager.ErrorList; } }
/// <summary> /// 20. simple-expression → additive-expression relop additive-expression /// |additive-expression /// 21. relop →<= | < | > | >= | == | != /// </summary> /// <returns></returns> private TreeNode SimpleExpression() { TreeNode p = AdditiveExpression(); currentToken = GetNextToken(); if (CheckCurrentToken(TokenType.LESSEQUAL) || CheckCurrentToken('<') || CheckCurrentToken('>') || CheckCurrentToken(TokenType.GREATERQUAL) || CheckCurrentToken(TokenType.EQUAL) || CheckCurrentToken(TokenType.NOTEQUAL)) { TreeNode temp = new TreeNode(ExpKind.OpK, (TokenType)currentToken.TokenTypes, currentToken.TokenInfo, currentToken.LineNumber, scope); temp.Child[0] = p; p = temp; if (p.Child[0] != null) p.Child[0].Father = p; currentToken = GetNextToken(); p.Child[1] = AdditiveExpression(); if (p.Child[1] != null) { p.Child[1].Father = p; } } else { --currentTokenIndex; } return p; }