/******************************************************************************* * Copyright (c) 2006, 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.cdt.core.dom.parser.upc; import static org.eclipse.cdt.internal.core.dom.parser.upc.UPCParsersym.TK_Completion; import static org.eclipse.cdt.internal.core.dom.parser.upc.UPCParsersym.TK_relaxed; import static org.eclipse.cdt.internal.core.dom.parser.upc.UPCParsersym.TK_shared; import static org.eclipse.cdt.internal.core.dom.parser.upc.UPCParsersym.TK_strict; import lpg.lpgjavaruntime.IToken; import org.eclipse.cdt.core.dom.ast.IASTDeclaration; import org.eclipse.cdt.core.dom.ast.IASTExpression; import org.eclipse.cdt.core.dom.ast.IASTStatement; import org.eclipse.cdt.core.dom.ast.IASTTypeIdExpression; import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression; import org.eclipse.cdt.core.dom.ast.c.ICASTDeclSpecifier; import org.eclipse.cdt.core.dom.lrparser.action.ITokenStream; import org.eclipse.cdt.core.dom.lrparser.action.ISecondaryParserFactory; import org.eclipse.cdt.core.dom.lrparser.action.ScopedStack; import org.eclipse.cdt.core.dom.lrparser.action.c99.C99BuildASTParserAction; import org.eclipse.cdt.core.dom.upc.ast.IUPCASTDeclSpecifier; import org.eclipse.cdt.core.dom.upc.ast.IUPCASTForallStatement; import org.eclipse.cdt.core.dom.upc.ast.IUPCASTKeywordExpression; import org.eclipse.cdt.core.dom.upc.ast.IUPCASTSynchronizationStatement; /** * Extension to the C99ParserAction that adds support fot building * an AST with UPC specific nodes. */ public class UPCParserAction extends C99BuildASTParserAction { private IUPCNodeFactory nodeFactory; /** * TODO why is the nodeFactory passed as an argument * @param nodeFactory * @param parser * @param tu */ public UPCParserAction(ITokenStream parser, ScopedStack<Object> astStack, IUPCNodeFactory nodeFactory, ISecondaryParserFactory parserFactory) { super(parser, astStack, nodeFactory, parserFactory); this.nodeFactory = nodeFactory; nodeFactory.setUseC99SizeofExpressions(); } @Override protected boolean isCompletionToken(IToken token) { return token.getKind() == TK_Completion; } /************************************************************************************** * Semantic actions **************************************************************************************/ public void consumeExpressionUnarySizeofOperator(int upcOp) { nodeFactory.setUseUPCSizeofExpressions(upcOp); super.consumeExpressionUnaryOperator(IASTUnaryExpression.op_sizeof); nodeFactory.setUseC99SizeofExpressions(); } public void consumeExpressionSizeofTypeId(int upcOp) { nodeFactory.setUseUPCSizeofExpressions(upcOp); super.consumeExpressionTypeId(IASTTypeIdExpression.op_sizeof); nodeFactory.setUseC99SizeofExpressions(); } /** * constant ::= 'MYTHREAD' | 'THREADS' | 'UPC_MAX_BLOCKSIZE' */ public void consumeKeywordExpression(int keywordKind) { IUPCASTKeywordExpression expr = nodeFactory.newKeywordExpression(keywordKind); setOffsetAndLength(expr); astStack.push(expr); } /** * synchronization_statement ::= 'upc_notify' expression ';' * | 'upc_notify' ';' * | 'upc_wait' expression ';' * | 'upc_wait' ';' * | 'upc_barrier' expression ';' * | 'upc_barrier' ';' * | 'upc_fence' ';' */ public void consumeStatementSynchronizationStatement(int statementKind, boolean hasBarrierExpr) { IASTExpression barrierExpression = hasBarrierExpr ? (IASTExpression) astStack.pop() : null; IUPCASTSynchronizationStatement statement = nodeFactory.newSyncronizationStatment(barrierExpression, statementKind); setOffsetAndLength(statement); astStack.push(statement); } /** * iteration_statement * ::= 'upc_forall' '(' expression ';' expression ';' expression ';' affinity ')' statement * | 'upc_forall' '(' declaration expression ';' expression ';' affinity ')' statement */ public void consumeStatementUPCForallLoop(boolean hasExpr1, boolean hasExpr2, boolean hasExpr3, boolean hasAffinity) { IASTStatement body = (IASTStatement) astStack.pop(); boolean affinityContinue = false; IASTExpression affinity = null; if(hasAffinity) { Object o = astStack.pop(); if(o instanceof IASTExpression) affinity = (IASTExpression)o; else if(o instanceof IToken) affinityContinue = true; } IASTExpression expr3 = hasExpr3 ? (IASTExpression) astStack.pop() : null; IASTExpression expr2 = hasExpr2 ? (IASTExpression) astStack.pop() : null; IASTStatement initializer = nodeFactory.newNullStatement(); if(hasExpr1) { // may be an expression or a declaration Object node = astStack.pop(); if(node instanceof IASTExpression) initializer = nodeFactory.newExpressionStatement((IASTExpression)node); else if(node instanceof IASTDeclaration) initializer = nodeFactory.newDeclarationStatement((IASTDeclaration)node); } IUPCASTForallStatement forStat = nodeFactory.newForallStatement(initializer, expr2, expr3, body, affinity); forStat.setAffinityContinue(affinityContinue); setOffsetAndLength(forStat); astStack.push(forStat); } /** * Temporary object used during the parsing of UPC declaration specifiers. * Stored temporarily on the astStack, but does not become part of the AST. * Makes parsing of layout qualifiers easier. * * @author Mike */ private static class UPCParserActionLayoutQualifier { public boolean hasStar = false; public IASTExpression expression = null; } /** * layout_qualifier ::= '[' constant_expression ']' * | '[' '*' ']' * | '[' ']' */ public void consumeLayoutQualifier(boolean hasExpression, boolean hasStar) { UPCParserActionLayoutQualifier layoutQualifier = new UPCParserActionLayoutQualifier(); layoutQualifier.hasStar = hasStar; if(hasExpression) { layoutQualifier.expression = (IASTExpression) astStack.pop(); } astStack.push(layoutQualifier); } /** * Overrides setSpecifier to add support for temporary layout qualifier nodes. */ @Override public void setSpecifier(ICASTDeclSpecifier declSpec, Object specifier) { if(specifier instanceof IToken) setTokenSpecifier((IUPCASTDeclSpecifier)declSpec, (IToken)specifier); else setLayoutQualifier((IUPCASTDeclSpecifier)declSpec, (UPCParserActionLayoutQualifier) specifier); } /** * Support for new declaration specifier keywords. * * 'shared' without [] is handled here * 'shared' with [] is handled in setLayoutQualifier(). */ protected void setTokenSpecifier(IUPCASTDeclSpecifier node, IToken token) { switch(token.getKind()) { case TK_relaxed: node.setReferenceType(IUPCASTDeclSpecifier.rt_relaxed); break; case TK_strict: node.setReferenceType(IUPCASTDeclSpecifier.rt_strict); break; case TK_shared: node.setSharedQualifier(IUPCASTDeclSpecifier.sh_shared_default_block_size); break; default: super.setSpecifier(node, token); } } /** * Handles layout qualifiers with block size specified. */ protected void setLayoutQualifier(IUPCASTDeclSpecifier node, UPCParserActionLayoutQualifier layoutQualifier) { if(layoutQualifier.hasStar) { node.setSharedQualifier(IUPCASTDeclSpecifier.sh_shared_pure_allocation); } else if(layoutQualifier.expression != null) { node.setSharedQualifier(IUPCASTDeclSpecifier.sh_shared_constant_expression); node.setBlockSizeExpression(layoutQualifier.expression); } else { node.setSharedQualifier(IUPCASTDeclSpecifier.sh_shared_indefinite_allocation); } } }