Basic representation and parsing of if and for statements. Loop headers and if statement conditions are not yet supported.
PiperOrigin-RevId: 203211526
diff --git a/lib/Parser/Parser.cpp b/lib/Parser/Parser.cpp
index 08157e5..dd0112e 100644
--- a/lib/Parser/Parser.cpp
+++ b/lib/Parser/Parser.cpp
@@ -149,11 +149,14 @@
ParseResult parseCFGFunc();
ParseResult parseMLFunc();
ParseResult parseBasicBlock(CFGFunctionParserState &functionState);
- MLStatement *parseMLStatement(MLFunction *currentFunction);
+ Statement *parseStatement(ParentType parent);
OperationInst *parseCFGOperation(CFGFunctionParserState &functionState);
TerminatorInst *parseTerminator(CFGFunctionParserState &functionState);
+ ForStmt *parseForStmt(ParentType parent);
+ IfStmt *parseIfStmt(ParentType parent);
+ ParseResult parseNestedStatements(NodeStmt *parent);
};
} // end anonymous namespace
@@ -976,7 +979,7 @@
// Parse the list of instructions.
while (!consumeIf(Token::kw_return)) {
- auto *stmt = parseMLStatement(function);
+ auto *stmt = parseStatement(function);
if (!stmt)
return ParseFailure;
function->stmtList.push_back(stmt);
@@ -991,18 +994,98 @@
return ParseSuccess;
}
-/// Parse an MLStatement
-/// TODO
+/// Statement.
///
-MLStatement *Parser::parseMLStatement(MLFunction *currentFunction) {
+/// ml-stmt ::= instruction | ml-for-stmt | ml-if-stmt
+/// TODO: fix terminology in MLSpec document. ML functions
+/// contain operation statements, not instructions.
+///
+Statement * Parser::parseStatement(ParentType parent) {
switch (curToken.getKind()) {
default:
- return (emitError("expected ML statement"), nullptr);
+ //TODO: parse OperationStmt
+ return (emitError("expected statement"), nullptr);
- // TODO: add parsing of ML statements
+ case Token::kw_for:
+ return parseForStmt(parent);
+
+ case Token::kw_if:
+ return parseIfStmt(parent);
}
}
+/// For statement.
+///
+/// ml-for-stmt ::= `for` ssa-id `=` lower-bound `to` upper-bound
+/// (`step` integer-literal)? `{` ml-stmt* `}`
+///
+ForStmt * Parser::parseForStmt(ParentType parent) {
+ consumeToken(Token::kw_for);
+
+ //TODO: parse loop header
+ ForStmt *stmt = new ForStmt(parent);
+ if (parseNestedStatements(stmt)) {
+ delete stmt;
+ return nullptr;
+ }
+ return stmt;
+}
+
+/// If statement.
+///
+/// ml-if-head ::= `if` ml-if-cond `{` ml-stmt* `}`
+/// | ml-if-head `else` `if` ml-if-cond `{` ml-stmt* `}`
+/// ml-if-stmt ::= ml-if-head
+/// | ml-if-head `else` `{` ml-stmt* `}`
+///
+IfStmt * Parser::parseIfStmt(PointerUnion<MLFunction *, NodeStmt *> parent) {
+ consumeToken(Token::kw_if);
+
+ //TODO: parse condition
+ IfStmt *stmt = new IfStmt(parent);
+ if (parseNestedStatements(stmt)) {
+ delete stmt;
+ return nullptr;
+ }
+
+ int clauseNum = 0;
+ while (consumeIf(Token::kw_else)) {
+ if (consumeIf(Token::kw_if)) {
+ //TODO: parse condition
+ }
+ ElseClause * clause = new ElseClause(stmt, clauseNum);
+ ++clauseNum;
+ if (parseNestedStatements(clause)) {
+ delete clause;
+ return nullptr;
+ }
+ }
+
+ return stmt;
+}
+
+///
+/// Parse `{` ml-stmt* `}`
+///
+ParseResult Parser::parseNestedStatements(NodeStmt *parent) {
+ if (!consumeIf(Token::l_brace))
+ return emitError("expected '{' before statement list");
+
+ if (consumeIf(Token::r_brace)) {
+ // TODO: parse OperationStmt
+ return ParseSuccess;
+ }
+
+ while (!consumeIf(Token::r_brace)) {
+ auto *stmt = parseStatement(parent);
+ if (!stmt)
+ return ParseFailure;
+ parent->children.push_back(stmt);
+ }
+
+ return ParseSuccess;
+}
+
//===----------------------------------------------------------------------===//
// Top-level entity parsing.
//===----------------------------------------------------------------------===//