00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 #include "comma/parser/Parser.h"
00010 
00011 using namespace comma;
00012 
00013 
00014 
00015 
00016 Node Parser::parseDirectName(NameOption option)
00017 {
00018     Location loc = currentLocation();
00019 
00020     switch (currentTokenCode()) {
00021     default:
00022         report(diag::UNEXPECTED_TOKEN) << currentTokenString();
00023         seekNameEnd();
00024         break;
00025 
00026     case Lexer::TKN_IDENTIFIER:
00027         if (IdentifierInfo *name = parseIdentifier())
00028             return client.acceptDirectName(name, loc, option);
00029         break;
00030 
00031     case Lexer::TKN_CHARACTER:
00032         if (IdentifierInfo *name = parseCharacter())
00033             return client.acceptCharacterLiteral(name, loc);
00034         break;
00035 
00036     case Lexer::TKN_PERCENT:
00037         return client.acceptPercent(ignoreToken());
00038 
00039     case Lexer::TKN_INJ:
00040         return parseInj();
00041 
00042     case Lexer::TKN_PRJ:
00043         return parsePrj();
00044     };
00045 
00046     return getInvalidNode();
00047 }
00048 
00049 Node Parser::parseInj()
00050 {
00051     assert(currentTokenIs(Lexer::TKN_INJ));
00052     Location loc = ignoreToken();
00053 
00054     if (!requireToken(Lexer::TKN_LPAREN))
00055         return getInvalidNode();
00056 
00057     Node expr = parseExpr();
00058 
00059     if (expr.isInvalid() || !requireToken(Lexer::TKN_RPAREN))
00060         return getInvalidNode();
00061 
00062     return client.acceptInj(loc, expr);
00063 }
00064 
00065 Node Parser::parsePrj()
00066 {
00067     assert(currentTokenIs(Lexer::TKN_PRJ));
00068     Location loc = ignoreToken();
00069 
00070     if (!requireToken(Lexer::TKN_LPAREN))
00071         return getInvalidNode();
00072 
00073     Node expr = parseExpr();
00074 
00075     if (expr.isInvalid() || !requireToken(Lexer::TKN_RPAREN)) {
00076         seekCloseParen();
00077         return getInvalidNode();
00078     }
00079 
00080     return client.acceptPrj(loc, expr);
00081 }
00082 
00083 Node Parser::parseSelectedComponent(Node prefix, NameOption option)
00084 {
00085     Location loc = currentLocation();
00086 
00087     if (reduceToken(Lexer::TKN_ALL))
00088         return client.acceptDereference(prefix, loc);
00089 
00090     IdentifierInfo *name = parseAnyIdentifier();
00091 
00092     if (name) {
00093         bool forStatement = (option == Statement_Name);
00094         return client.acceptSelectedComponent(prefix, name, loc, forStatement);
00095     }
00096 
00097     seekNameEnd();
00098     return getInvalidNode();
00099 }
00100 
00101 Node Parser::parseApplication(Node prefix)
00102 {
00103     assert(currentTokenIs(Lexer::TKN_LPAREN));
00104 
00105     if (unitExprFollows()) {
00106         Location loc = ignoreToken(); 
00107         ignoreToken();                
00108         Node result = client.finishName(prefix);
00109         if (result.isValid())
00110             report(loc, diag::EMPTY_PARAMS);
00111         return result;
00112     }
00113 
00114     ignoreToken();              
00115     NodeVector arguments;
00116     bool seenSelector = false;
00117 
00118     do {
00119         Node arg = getInvalidNode();
00120         if (keywordSelectionFollows()) {
00121             arg = parseParameterAssociation();
00122             seenSelector = true;
00123         }
00124         else if (seenSelector) {
00125             report(diag::POSITIONAL_FOLLOWING_SELECTED_PARAMETER);
00126             seekCloseParen();
00127             return getInvalidNode();
00128         }
00129         else
00130             arg = parseExpr();
00131 
00132         if (arg.isValid())
00133             arguments.push_back(arg);
00134         else {
00135             seekCloseParen();
00136             return getInvalidNode();
00137         }
00138     } while (reduceToken(Lexer::TKN_COMMA));
00139 
00140     if (!requireToken(Lexer::TKN_RPAREN)) {
00141         seekCloseParen();
00142         return getInvalidNode();
00143     }
00144     return client.acceptApplication(prefix, arguments);
00145 }
00146 
00147 Node Parser::parseParameterAssociation()
00148 {
00149     assert(keywordSelectionFollows());
00150 
00151     Location loc = currentLocation();
00152     IdentifierInfo *key = parseIdentifier();
00153 
00154     ignoreToken();              
00155 
00156     Node rhs = parseExpr();
00157 
00158     if (rhs.isValid())
00159         return client.acceptParameterAssociation(key, loc, rhs);
00160     else
00161         return getInvalidNode();
00162 }
00163 
00164 Node Parser::parseAttribute(Node prefix, NameOption option)
00165 {
00166     assert(attributeFollows());
00167     ignoreToken();              
00168 
00169     Location loc = currentLocation();
00170     IdentifierInfo *name = parseIdentifier();
00171 
00172     if (name->getAttributeID() == attrib::UNKNOWN_ATTRIBUTE) {
00173         report(loc, diag::UNKNOWN_ATTRIBUTE) << name;
00174         return getInvalidNode();
00175     }
00176 
00179     if ((name->getAttributeID() == attrib::Range) &&
00180         (option != Accept_Range_Attribute)) {
00181         report(loc, diag::INVALID_ATTRIBUTE_CONTEXT) << name;
00182         return getInvalidNode();
00183     }
00184 
00185     return client.acceptAttribute(prefix, name, loc);
00186 }
00187 
00188 Node Parser::parseName(NameOption option)
00189 {
00190     Location loc = currentLocation();
00191 
00192     
00193     Node prefix = parseDirectName(option);
00194 
00195     if (prefix.isInvalid())
00196         return prefix;
00197 
00198     for ( ;; ) {
00199         if (currentTokenIs(Lexer::TKN_LPAREN))
00200             prefix = parseApplication(prefix);
00201         else if (reduceToken(Lexer::TKN_DOT)) {
00202             prefix = client.finishName(prefix);
00203             if (prefix.isValid())
00204                 prefix = parseSelectedComponent(prefix, option);
00205         }
00206         else if (attributeFollows()) {
00207             prefix = client.finishName(prefix);
00208             if (prefix.isValid())
00209                 prefix = parseAttribute(prefix, option);
00210         }
00211         else
00212             break;
00213 
00214         if (prefix.isInvalid())
00215             break;
00216     }
00217 
00218     if (prefix.isInvalid()) {
00219         seekNameEnd();
00220         return prefix;
00221     }
00222     else
00223         return client.finishName(prefix);
00224 }
00225 
00226 void Parser::seekNameEnd()
00227 {
00228     for ( ;; ) {
00229         switch(currentTokenCode()) {
00230 
00231         default:
00232             return;
00233 
00234         case Lexer::TKN_IDENTIFIER:
00235         case Lexer::TKN_DOT:
00236         case Lexer::TKN_CHARACTER:
00237         case Lexer::TKN_PERCENT:
00238         case Lexer::TKN_INJ:
00239         case Lexer::TKN_PRJ:
00240         case Lexer::TKN_ALL:
00241             ignoreToken();
00242             break;
00243 
00244         case Lexer::TKN_LPAREN:
00245             ignoreToken();
00246             seekCloseParen();
00247         };
00248     }
00249 }
00250 
00251 bool Parser::consumeName()
00252 {
00253     
00254     
00255     switch (currentTokenCode()) {
00256     default:
00257         return false;
00258     case Lexer::TKN_CHARACTER:
00259     case Lexer::TKN_IDENTIFIER:
00260     case Lexer::TKN_PERCENT:
00261     case Lexer::TKN_INJ:
00262     case Lexer::TKN_PRJ:
00263         break;
00264     }
00265 
00266     
00267     ignoreToken();
00268 
00269     
00270     
00271     
00272     bool consume = true;
00273     while (consume) {
00274         if (reduceToken(Lexer::TKN_LPAREN))
00275             consume = seekCloseParen();
00276         else if (reduceToken(Lexer::TKN_DOT)) {
00277             switch (currentTokenCode()) {
00278             default:
00279                 consume = false;
00280                 break;
00281             case Lexer::TKN_IDENTIFIER:
00282             case Lexer::TKN_CHARACTER:
00283             case Lexer::TKN_ALL:
00284                 ignoreToken();
00285                 break;
00286             };
00287         }
00288         else if (attributeFollows()) {
00289             ignoreToken();      
00290             ignoreToken();      
00291         }
00292         else
00293             consume = false;
00294     }
00295     return true;
00296 }
00297