public static LinkedListNode <Lexeme> TryParse(LinkedListNode <Lexeme> lexemes, out AssignStmt resultNode, bool needSC = true) { resultNode = null; var nextLexeme = Var.TryParse(lexemes, out Var lhs); if (lhs == null) { return(lexemes); } AssignOp op = AssignOp.ASSIGN; if (nextLexeme.Value.Type == LT.OP_ADD || nextLexeme.Value.Type == LT.OP_SUB || nextLexeme.Value.Type == LT.OP_MUL || nextLexeme.Value.Type == LT.OP_DIV || nextLexeme.Value.Type == LT.OP_MOD) { op = TypeToOp(nextLexeme.Value.Type); nextLexeme = nextLexeme.Next; } if (nextLexeme.Value.Type != LT.OP_ASSIGN) { return(lexemes); } Lexeme token = nextLexeme.Value; nextLexeme = Expr.TryParse(nextLexeme.Next, out Expr rhs); if (rhs == null) { throw new Exception($"Unrecognized right hand member of operator '{OpName(op)}' at {nextLexeme.Value.File}:{nextLexeme.Value.Line}"); } if (needSC) { if (nextLexeme.Value.Type != LT.OP_SC) { throw new Exception($"Missing semicolon after statement at {nextLexeme.Value.File}:{nextLexeme.Value.Line}"); } nextLexeme = nextLexeme.Next; } resultNode = new AssignStmt { LHS = lhs, RHS = rhs, Op = op, Token = token }; return(nextLexeme); }
public static LinkedListNode <Lexeme> TryParse(LinkedListNode <Lexeme> lexemes, out ForLoop resultNode) { resultNode = null; if (lexemes.Value.Type != LT.KW_FOR) { return(lexemes); } var nextLexeme = lexemes.Next; if (nextLexeme.Value.Type != LT.OP_PAREN_O) { throw new Exception($"Missing loop header at {nextLexeme.Value.File}:{nextLexeme.Value.Line}"); } nextLexeme = nextLexeme.Next; nextLexeme = DeclStmt.TryParse(nextLexeme, out DeclStmt ds); if (ds == null || !(ds is DeclAssignStmt init)) { throw new Exception($"Cannot parse loop initializer at {nextLexeme.Value.File}:{nextLexeme.Value.Line}"); } nextLexeme = BinaryExpr.TryParseExpr(nextLexeme, out Expr cond); if (cond == null) { throw new Exception($"Cannot parse loop condition at {nextLexeme.Value.File}:{nextLexeme.Value.Line}"); } if (nextLexeme.Value.Type != LT.OP_SC) { throw new Exception($"Missing semicolon after loop condition at {nextLexeme.Value.File}:{nextLexeme.Value.Line}"); } nextLexeme = nextLexeme.Next; nextLexeme = AssignStmt.TryParse(nextLexeme, out AssignStmt upd, false); if (upd == null) { throw new Exception($"Cannot parse loop afterthought at {nextLexeme.Value.File}:{nextLexeme.Value.Line}"); } if (nextLexeme.Value.Type != LT.OP_PAREN_C) { throw new Exception($"Missing closing parenthesis for loop header at {nextLexeme.Value.File}:{nextLexeme.Value.Line}"); } nextLexeme = nextLexeme.Next; Stmt stmt; List <Stmt> stmts = new List <Stmt>(); if (nextLexeme.Value.Type == LT.OP_BRACE_O) { // block body nextLexeme = nextLexeme.Next; nextLexeme = Stmt.TryParse(nextLexeme, out stmt); while (stmt != null) { stmts.Add(stmt); nextLexeme = Stmt.TryParse(nextLexeme, out stmt); } if (nextLexeme.Value.Type != LT.OP_BRACE_C) { throw new Exception($"Missing closing bracket for loop body at {nextLexeme.Value.File}:{nextLexeme.Value.Line}"); } nextLexeme = nextLexeme.Next; } else { // single statement body nextLexeme = Stmt.TryParse(nextLexeme, out stmt); if (stmt == null) { throw new Exception($"Missing loop body at {nextLexeme.Value.File}:{nextLexeme.Value.Line}"); } stmts.Add(stmt); } resultNode = new ForLoop { Init = init, Condition = cond, Update = upd, Body = new BlockBody(stmts) }; return(nextLexeme); }
public static LinkedListNode <Lexeme> TryParse(LinkedListNode <Lexeme> lexemes, out Stmt resultNode) { resultNode = null; if (lexemes.Value.Type == LT.OP_SC) { resultNode = new BlankStmt(); return(lexemes.Next); } var nextLexeme = IfStmt.TryParse(lexemes, out IfStmt sif); if (sif != null) { resultNode = sif; return(nextLexeme); } nextLexeme = TryParseStruct(lexemes, out Stmt stmt); if (stmt != null) { resultNode = stmt; return(nextLexeme); } nextLexeme = FnCall.TryParse(lexemes, out FnCall fnc); if (fnc != null) { if (nextLexeme.Value.Type == LT.OP_SC) { resultNode = new ExprStmt <FnCall>(fnc); return(nextLexeme.Next); } } nextLexeme = ForLoop.TryParse(lexemes, out ForLoop fl); if (fl != null) { resultNode = fl; return(nextLexeme); } nextLexeme = WhileLoop.TryParse(lexemes, out WhileLoop wl); if (wl != null) { resultNode = wl; return(nextLexeme); } nextLexeme = AssignStmt.TryParse(lexemes, out AssignStmt sa); if (sa != null) { resultNode = sa; return(nextLexeme); } nextLexeme = ReturnStmt.TryParse(lexemes, out ReturnStmt sr); if (sr != null) { resultNode = sr; return(nextLexeme); } if (lexemes.Value.Type == LT.KW_BREAK) { if (lexemes.Next.Value.Type != LT.OP_SC) { throw new Exception($"Missing semicolon after break keyword at {lexemes.Value.File}:{lexemes.Value.Line}"); } resultNode = new BreakStmt { Token = lexemes.Value }; return(lexemes.Next.Next); } if (lexemes.Value.Type == LT.KW_CONT) { if (lexemes.Next.Value.Type != LT.OP_SC) { throw new Exception($"Missing semicolon after continue keyword at {lexemes.Value.File}:{lexemes.Value.Line}"); } resultNode = new ContinueStmt { Token = lexemes.Value }; return(lexemes.Next.Next); } return(lexemes); }