blob: 95628e3b9c4b47b0f9ad3e06afdac118a6dd5edb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2006, 2010 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.cdt.core.lrparser.tests;
import org.eclipse.cdt.core.dom.ast.IASTArrayDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTArrayModifier;
import org.eclipse.cdt.core.dom.ast.IASTArraySubscriptExpression;
import org.eclipse.cdt.core.dom.ast.IASTBinaryExpression;
import org.eclipse.cdt.core.dom.ast.IASTCompoundStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclarationStatement;
import org.eclipse.cdt.core.dom.ast.IASTDeclarator;
import org.eclipse.cdt.core.dom.ast.IASTEqualsInitializer;
import org.eclipse.cdt.core.dom.ast.IASTExpressionStatement;
import org.eclipse.cdt.core.dom.ast.IASTFunctionCallExpression;
import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition;
import org.eclipse.cdt.core.dom.ast.IASTInitializerClause;
import org.eclipse.cdt.core.dom.ast.IASTLiteralExpression;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorMacroDefinition;
import org.eclipse.cdt.core.dom.ast.IASTPreprocessorStatement;
import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration;
import org.eclipse.cdt.core.dom.ast.IASTStatement;
import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit;
import org.eclipse.cdt.core.dom.ast.IASTUnaryExpression;
import org.eclipse.cdt.core.dom.lrparser.gnu.GCCLanguage;
import org.eclipse.cdt.core.model.ILanguage;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* TODO these tests can be moved into the core
*/
@SuppressWarnings("nls")
public class LRDigraphTrigraphTests extends TestCase {
public static TestSuite suite() {
return new TestSuite(LRDigraphTrigraphTests.class);
}
public LRDigraphTrigraphTests() {
}
public LRDigraphTrigraphTests(String name) {
super(name);
}
protected IASTTranslationUnit parse(String code) {
ParseHelper.Options options = new ParseHelper.Options();
options.setCheckSyntaxProblems(true);
options.setCheckPreprocessorProblems(true);
return ParseHelper.parse(code, getCLanguage(), options);
}
protected ILanguage getCLanguage() {
return GCCLanguage.getDefault();
}
public void testTrigraphSequences() {
String code = "??=define SIZE ??/ \n" + // trigraph used as backslash to ignore newline
"99 \n" + "int main(void)??< \n" + " int arr??(SIZE??); \n"
+ " arr??(4??) = '0' - (??-0 ??' 1 ??! 2); \n" + " printf(\"%c??/n\", arr??(4??)); \n"
+ "??> \n";
IASTTranslationUnit tu = parse(code);
assertNotNull(tu);
IASTPreprocessorStatement[] defines = tu.getAllPreprocessorStatements();
assertEquals(1, defines.length);
IASTPreprocessorMacroDefinition macro = (IASTPreprocessorMacroDefinition) defines[0];
assertEquals("SIZE", macro.getName().toString());
//assertEquals("99", macro.getExpansion());
IASTFunctionDefinition main = (IASTFunctionDefinition) tu.getDeclarations()[0];
IASTCompoundStatement body = (IASTCompoundStatement) main.getBody();
IASTStatement[] statements = body.getStatements();
assertEquals(3, statements.length);
// int arr??(SIZE??);
IASTSimpleDeclaration arr = (IASTSimpleDeclaration) ((IASTDeclarationStatement) statements[0]).getDeclaration();
IASTArrayDeclarator arr_decl = (IASTArrayDeclarator) arr.getDeclarators()[0];
IASTArrayModifier modifier = arr_decl.getArrayModifiers()[0];
IASTLiteralExpression lit = (IASTLiteralExpression) modifier.getConstantExpression();
assertEquals(IASTLiteralExpression.lk_integer_constant, lit.getKind());
// arr??(4??) = '0' - (??-0 ??' 1 ??! 2);
IASTBinaryExpression expr = (IASTBinaryExpression) ((IASTExpressionStatement) statements[1]).getExpression();
assertEquals(IASTBinaryExpression.op_assign, expr.getOperator());
IASTArraySubscriptExpression arr_op = (IASTArraySubscriptExpression) expr.getOperand1();
assertEquals("4", ((IASTLiteralExpression) arr_op.getSubscriptExpression()).toString());
IASTBinaryExpression cond = (IASTBinaryExpression) ((IASTUnaryExpression) ((IASTBinaryExpression) expr
.getOperand2()).getOperand2()).getOperand();
assertEquals(IASTBinaryExpression.op_binaryOr, cond.getOperator());
IASTBinaryExpression cond2 = (IASTBinaryExpression) cond.getOperand1();
assertEquals(IASTBinaryExpression.op_binaryXor, cond2.getOperator());
IASTUnaryExpression not = (IASTUnaryExpression) cond2.getOperand1();
assertEquals(IASTUnaryExpression.op_tilde, not.getOperator());
// printf(\"%c??/n\", arr??(4??));
IASTFunctionCallExpression expr2 = (IASTFunctionCallExpression) ((IASTExpressionStatement) statements[2])
.getExpression();
IASTInitializerClause[] args = expr2.getArguments();
IASTArraySubscriptExpression arr_op2 = (IASTArraySubscriptExpression) args[1];
assertEquals("4", ((IASTLiteralExpression) arr_op2.getSubscriptExpression()).toString());
}
public void testTrigraphEscapeSequences() {
// a ??/ trigraph should act just like a backslash in a string literal
String code = "int main(void)??< \n" + " char str[] = \"??/\"??/n\"; \n" + " char c = '??/u0000'; \n"
+ "??> \n";
parse(code); // will throw an exception if there are parse errors
}
public void testDigraphSequences() {
String code = "%:define join(a, b) a %:%: b \n" + "int main() <% \n" + " int arr<:5:>; \n" + "%> \n";
IASTTranslationUnit tu = parse(code); // will throw an exception if there are parse errors
IASTFunctionDefinition main = (IASTFunctionDefinition) tu.getDeclarations()[0];
IASTCompoundStatement body = (IASTCompoundStatement) main.getBody();
IASTStatement[] statements = body.getStatements();
assertEquals(1, statements.length);
IASTSimpleDeclaration arr = (IASTSimpleDeclaration) ((IASTDeclarationStatement) statements[0]).getDeclaration();
IASTArrayDeclarator arr_decl = (IASTArrayDeclarator) arr.getDeclarators()[0];
IASTArrayModifier modifier = arr_decl.getArrayModifiers()[0];
IASTLiteralExpression lit = (IASTLiteralExpression) modifier.getConstantExpression();
assertEquals("5", lit.toString());
}
public void testTrigraphAndDigraphSequecesInPreprocessorDirectives() {
String code = "%:define join1(a, b) a %:%: b \n" + "%:define str1(a) %: a \n"
+ "??=define join2(a, b) a ??=??= b \n" + "??=define str2(a) ??= a \n" + "int main() <% \n"
+ " int join1(x, y) = str1(its all good); \n" + " int join2(a, b) = str2(its still good); \n"
+ "%> \n";
IASTTranslationUnit tu = parse(code); // will throw an exception if there are parse errors
IASTFunctionDefinition main = (IASTFunctionDefinition) tu.getDeclarations()[0];
IASTCompoundStatement body = (IASTCompoundStatement) main.getBody();
IASTStatement[] statements = body.getStatements();
assertEquals(2, statements.length);
IASTSimpleDeclaration decl1 = (IASTSimpleDeclaration) ((IASTDeclarationStatement) statements[0])
.getDeclaration();
IASTDeclarator declarator1 = decl1.getDeclarators()[0];
assertEquals("xy", declarator1.getName().toString());
IASTLiteralExpression expr1 = (IASTLiteralExpression) ((IASTEqualsInitializer) declarator1.getInitializer())
.getInitializerClause();
assertEquals(IASTLiteralExpression.lk_string_literal, expr1.getKind());
assertEquals("\"its all good\"", expr1.toString());
IASTSimpleDeclaration decl2 = (IASTSimpleDeclaration) ((IASTDeclarationStatement) statements[1])
.getDeclaration();
IASTDeclarator declarator2 = decl2.getDeclarators()[0];
assertEquals("ab", declarator2.getName().toString());
IASTLiteralExpression expr2 = (IASTLiteralExpression) ((IASTEqualsInitializer) declarator2.getInitializer())
.getInitializerClause();
assertEquals(IASTLiteralExpression.lk_string_literal, expr2.getKind());
assertEquals("\"its still good\"", expr2.toString());
}
}