about summary refs log tree commit diff homepage
path: root/lib/Expr/Parser.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Expr/Parser.cpp')
-rw-r--r--lib/Expr/Parser.cpp74
1 files changed, 42 insertions, 32 deletions
diff --git a/lib/Expr/Parser.cpp b/lib/Expr/Parser.cpp
index e664c9dd..b73c72d6 100644
--- a/lib/Expr/Parser.cpp
+++ b/lib/Expr/Parser.cpp
@@ -1132,20 +1132,33 @@ VersionResult ParserImpl::ParseVersionSpecifier() {
   return Res;
 }
 
-/// version - '[' update-list? ']' ['@' version-specifier]
+namespace {
+  /// WriteInfo - Helper class used for storing information about a parsed
+  /// write, prior to type checking.
+  struct WriteInfo {
+    NumberOrExprResult LHS;
+    NumberOrExprResult RHS;
+    Token LHSTok;
+    Token RHSTok;
+    
+    WriteInfo(NumberOrExprResult _LHS, NumberOrExprResult _RHS,
+              Token _LHSTok, Token _RHSTok) : LHS(_LHS), RHS(_RHS),
+                                              LHSTok(_LHSTok), RHSTok(_RHSTok) {
+    }
+  };
+}
+
+/// version - '[' update-list? ']' '@' version-specifier
 /// update-list - empty
 /// update-list - lhs '=' rhs [',' update-list]
 VersionResult ParserImpl::ParseVersion() {
   if (Tok.kind != Token::LSquare)
     return VersionResult(false, UpdateList(0, false, NULL));
   
-  std::vector< std::pair<NumberOrExprResult, NumberOrExprResult> > Writes;
+  std::vector<WriteInfo> Writes;
   ConsumeLSquare();
   for (;;) {
-    // FIXME: Type check exprs.
-
-    // FIXME: We need to do this (the above) anyway just to handle
-    // implicit constants correctly.
+    Token LHSTok = Tok;
     NumberOrExprResult LHS = ParseNumberOrExpr();
     
     if (Tok.kind != Token::Equals) {
@@ -1154,9 +1167,10 @@ VersionResult ParserImpl::ParseVersion() {
     }
     
     ConsumeToken();
+    Token RHSTok = Tok;
     NumberOrExprResult RHS = ParseNumberOrExpr();
 
-    Writes.push_back(std::make_pair(LHS, RHS));
+    Writes.push_back(WriteInfo(LHS, RHS, LHSTok, RHSTok));
     
     if (Tok.kind == Token::Comma)
       ConsumeToken();
@@ -1167,48 +1181,44 @@ VersionResult ParserImpl::ParseVersion() {
 
   VersionHandle Base(0, false, NULL);
 
-  // Anonymous array case.
-  if (Tok.kind != Token::At) { 
-    Array *root = new Array(0, 0, 0);
-    Base = UpdateList(root, false, NULL);
-  } else {
-    ConsumeToken();
+  if (Tok.kind != Token::At) {
+    Error("expected '@'.", Tok);
+    return VersionResult(false, UpdateList(0, true, NULL));
+  } 
 
-    VersionResult BaseRes = ParseVersionSpecifier();
-    if (!BaseRes.isValid())
-      return BaseRes;
+  ConsumeExpectedToken(Token::At);
 
-    Base = BaseRes.get();
-  }
+  VersionResult BaseRes = ParseVersionSpecifier();
+  if (!BaseRes.isValid())
+    return BaseRes;
+
+  Base = BaseRes.get();
 
   Expr::Width ArrayDomainType = Expr::Int32;
   Expr::Width ArrayRangeType = Expr::Int8;
 
-  for (std::vector< std::pair<NumberOrExprResult, NumberOrExprResult> >::reverse_iterator
-         it = Writes.rbegin(), ie = Writes.rend(); it != ie; ++it) {
+  for (std::vector<WriteInfo>::reverse_iterator it = Writes.rbegin(), 
+         ie = Writes.rend(); it != ie; ++it) {
+    const WriteInfo &WI = *it;
     ExprResult LHS, RHS;
     // FIXME: This can be factored into common helper for coercing a
     // NumberOrExpr into an Expr.
-    if (it->first.isNumber()) {
-      LHS = ParseNumberToken(ArrayDomainType, it->first.getNumber());
+    if (WI.LHS.isNumber()) {
+      LHS = ParseNumberToken(ArrayDomainType, WI.LHS.getNumber());
     } else {
-      LHS = it->first.getExpr(); 
+      LHS = WI.LHS.getExpr();
       if (LHS.isValid() && LHS.get()->getWidth() != ArrayDomainType) {
-        // FIXME: bad token location. We should maybe try and know the
-        // array up-front?
-        Error("invalid value in write index (doesn't match domain).", Tok);
+        Error("invalid write index (doesn't match array domain).", WI.LHSTok);
         LHS = ExprResult();
       }
     }
 
-    if (it->second.isNumber()) {
-      RHS = ParseNumberToken(ArrayRangeType, it->second.getNumber());
+    if (WI.RHS.isNumber()) {
+      RHS = ParseNumberToken(ArrayRangeType, WI.RHS.getNumber());
     } else {
-      RHS = it->second.getExpr();
+      RHS = WI.RHS.getExpr();
       if (RHS.isValid() && RHS.get()->getWidth() != ArrayRangeType) {
-        // FIXME: bad token location. We should maybe try and know the
-        // array up-front?
-        Error("invalid value in write assignment (doesn't match range).", Tok);
+        Error("invalid write value (doesn't match array range).", WI.RHSTok);
         RHS = ExprResult();
       }
     }