| /******************************************************************************* |
| * Copyright (c) 2013, 2014 Etienne Bergeron |
| * |
| * All rights reserved. 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: |
| * Etienne Bergeron - Initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.tracecompass.ctf.parser.tests; |
| |
| import static org.junit.Assert.assertEquals; |
| import static org.junit.Assert.fail; |
| |
| import org.antlr.runtime.ANTLRStringStream; |
| import org.antlr.runtime.CharStream; |
| import org.antlr.runtime.CommonTokenStream; |
| import org.antlr.runtime.RecognitionException; |
| import org.antlr.runtime.tree.CommonTree; |
| import org.eclipse.tracecompass.ctf.parser.CTFLexer; |
| import org.eclipse.tracecompass.ctf.parser.CTFParser; |
| import org.junit.Ignore; |
| import org.junit.Test; |
| |
| /** |
| * This test validates the CTF-Parser implementation. |
| * |
| * The goal of these tests is to validate syntactic rules and not the CTF |
| * semantic. Each test parses a string with a given rule of the compiled parser |
| * and validates the resulting tree by using match rules. |
| * |
| * @author Etienne Bergeron |
| */ |
| public class CtfParserTest { |
| |
| // ------------------------------------------------------------------------ |
| // Attributes |
| // ------------------------------------------------------------------------ |
| |
| private CTFParser parser; |
| |
| // ------------------------------------------------------------------------ |
| // Matches - Helper class and functions to match a parsed tree. |
| // ------------------------------------------------------------------------ |
| |
| private class TreeMatcher { |
| int fType; |
| String fText; |
| TreeMatcher[] fChild; |
| |
| TreeMatcher(int type, String text, TreeMatcher child[]) { |
| fType = type; |
| fText = text; |
| fChild = child; |
| } |
| |
| void matches(CommonTree tree) { |
| if (fType == -1) { |
| return; |
| } |
| if (tree.getType() != fType) { |
| fail("Type mismatch!" + |
| " expected:" + fType + |
| " actual:" + tree.getType()); |
| } |
| |
| if (fText != null) { |
| if (!fText.equals(tree.getText())) { |
| fail("Text mismatch!" + |
| " expected:" + fText + |
| " actual:" + tree.getText()); |
| } |
| } |
| |
| if (fChild != null) { |
| int size = fChild.length; |
| if (tree.getChildren() == null) { |
| if (size != 0) { |
| fail("Invalid children!" |
| + "Expect: " + size + "child"); |
| } |
| } else { |
| if (tree.getChildren().size() != size) { |
| fail("Invalid number of childs!" |
| + " expected:" + size |
| + " actual:" + tree.getChildren().size()); |
| } |
| |
| for (int i = 0; i < size; ++i) { |
| fChild[i].matches((CommonTree) tree.getChild(i)); |
| } |
| } |
| } |
| } |
| } |
| |
| void Matches(TreeMatcher matcher, CommonTree tree) { |
| if (tree == null) { |
| fail("Parsing failed!"); |
| } |
| matcher.matches(tree); |
| } |
| |
| TreeMatcher All() { |
| return new TreeMatcher(-1, null, null); |
| } |
| |
| TreeMatcher Node(int type, TreeMatcher... child) { |
| return new TreeMatcher(type, null, child); |
| } |
| |
| TreeMatcher Node(int type, String text, TreeMatcher... child) { |
| return new TreeMatcher(type, text, child); |
| } |
| |
| TreeMatcher List(TreeMatcher... child) { |
| return new TreeMatcher(0, null, child); |
| } |
| |
| // ------------------------------------------------------------------------ |
| // Operations |
| // ------------------------------------------------------------------------ |
| |
| private void setInput(String content) { |
| CharStream cs = new ANTLRStringStream(content); |
| CTFLexer lexer = new CTFLexer(cs); |
| CommonTokenStream tokens = new CommonTokenStream(lexer); |
| parser = new CTFParser(tokens, false); |
| } |
| |
| private CommonTree primaryExpression(String content) { |
| try { |
| setInput(content); |
| return parser.primaryExpression().getTree(); |
| } catch (RecognitionException e) { |
| return null; |
| } |
| } |
| |
| private CommonTree unaryExpression(String content) { |
| try { |
| setInput(content); |
| return parser.unaryExpression().getTree(); |
| } catch (RecognitionException e) { |
| return null; |
| } |
| } |
| |
| private CommonTree declaration(String content) { |
| try { |
| setInput(content); |
| return parser.declaration().getTree(); |
| } catch (RecognitionException e) { |
| return null; |
| } |
| } |
| |
| // ------------------------------------------------------------------------ |
| // Test cases |
| // ------------------------------------------------------------------------ |
| |
| /** |
| * Validate that parsing of an empty expression is invalid. |
| */ |
| @Test |
| public void testPrimaryExpression() { |
| CommonTree tree_empty = primaryExpression(""); |
| assertEquals(null, tree_empty); |
| } |
| |
| /** |
| * Validate parsing of literals through a primary expression |
| */ |
| @Test |
| public void testIntegerLiteralPrimaryExpression() { |
| Matches(Node(CTFParser.UNARY_EXPRESSION_DEC, |
| Node(CTFParser.DECIMAL_LITERAL, "123")), |
| primaryExpression("123")); |
| |
| Matches(Node(CTFParser.UNARY_EXPRESSION_HEX, |
| Node(CTFParser.HEX_LITERAL, "0x123")), |
| primaryExpression("0x123")); |
| |
| Matches(Node(CTFParser.UNARY_EXPRESSION_OCT, |
| Node(CTFParser.OCTAL_LITERAL, "0123")), |
| primaryExpression("0123")); |
| |
| Matches(Node(CTFParser.UNARY_EXPRESSION_DEC, |
| Node(CTFParser.DECIMAL_LITERAL, "123"), |
| Node(CTFParser.SIGN, "-")), |
| primaryExpression("-123")); |
| |
| Matches(Node(CTFParser.UNARY_EXPRESSION_DEC, |
| Node(CTFParser.DECIMAL_LITERAL, "123"), |
| Node(CTFParser.SIGN, "-")), |
| primaryExpression(" - 123")); |
| |
| Matches(Node(CTFParser.UNARY_EXPRESSION_DEC, |
| Node(CTFParser.DECIMAL_LITERAL, "123"), |
| Node(CTFParser.SIGN, "-"), |
| Node(CTFParser.SIGN, "-"), |
| Node(CTFParser.SIGN, "+")), |
| primaryExpression(" - - + 123")); |
| |
| Matches(Node(CTFParser.UNARY_EXPRESSION_HEX, |
| Node(CTFParser.HEX_LITERAL, "0x123"), |
| Node(CTFParser.SIGN, "+"), |
| Node(CTFParser.SIGN, "-")), |
| primaryExpression("+ - 0x123")); |
| |
| Matches(Node(CTFParser.UNARY_EXPRESSION_OCT, |
| Node(CTFParser.OCTAL_LITERAL, "0123"), |
| Node(CTFParser.SIGN, "+"), |
| Node(CTFParser.SIGN, "-")), |
| primaryExpression("+ - 0123")); |
| } |
| |
| /** |
| * Validate parsing of a character literals through a primary expression |
| */ |
| @Test |
| public void testCharacterLiteralPrimaryExpression() { |
| Matches(Node(CTFParser.CHARACTER_LITERAL, "'a'"), |
| primaryExpression("'a'")); |
| |
| Matches(Node(CTFParser.CHARACTER_LITERAL, "'\\n'"), |
| primaryExpression("'\\n'")); |
| } |
| |
| /** |
| * Validate parsing of a string literals through a primary expression |
| */ |
| @Test |
| public void testStringLiteralPrimaryExpression() { |
| Matches(Node(CTFParser.UNARY_EXPRESSION_STRING_QUOTES, |
| Node(CTFParser.STRING_LITERAL, "\"aaa\"")), |
| primaryExpression("\"aaa\"")); |
| |
| Matches(Node(CTFParser.UNARY_EXPRESSION_STRING_QUOTES, |
| Node(CTFParser.STRING_LITERAL, "L\"aaa\"")), |
| primaryExpression("L\"aaa\"")); |
| |
| Matches(Node(CTFParser.UNARY_EXPRESSION_STRING_QUOTES, |
| Node(CTFParser.STRING_LITERAL, "\"aaa\\n\"")), |
| primaryExpression("\"aaa\\n\"")); |
| } |
| |
| /** |
| * Validate parsing of keywords through a primary expression |
| */ |
| @Test |
| public void testKeywordPrimaryExpression() { |
| Matches(Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.SIGNEDTOK, "signed")), |
| primaryExpression("signed")); |
| Matches(Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.ALIGNTOK, "align")), |
| primaryExpression("align")); |
| } |
| |
| /** |
| * Validate parsing of identifiers through a primary expression |
| */ |
| @Test |
| public void testIdentifierPrimaryExpression() { |
| Matches(Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "x")), |
| primaryExpression("x")); |
| Matches(Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "_123")), |
| primaryExpression("_123")); |
| } |
| |
| /** |
| * Validate that parsing of an empty unary expression is invalid. |
| */ |
| @Test |
| public void testUnaryExpression() { |
| CommonTree tree_empty = unaryExpression(""); |
| assertEquals(null, tree_empty); |
| } |
| |
| /** |
| * Validate parsing primary expression through an unary expression |
| */ |
| @Test |
| public void testSimpleUnaryExpression() { |
| Matches(Node(CTFParser.UNARY_EXPRESSION_DEC, |
| Node(CTFParser.DECIMAL_LITERAL, "123")), |
| unaryExpression("123")); |
| |
| Matches(Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "x")), |
| unaryExpression("x")); |
| } |
| |
| /** |
| * Validate parsing array through an unary expression |
| */ |
| @Test |
| public void testArrayUnaryExpression() { |
| Matches(List(Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "x")), |
| Node(CTFParser.OPENBRAC), |
| Node(CTFParser.UNARY_EXPRESSION_DEC, |
| Node(CTFParser.DECIMAL_LITERAL, "1"))), |
| unaryExpression("x[1]")); |
| |
| Matches(List(Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "x")), |
| Node(CTFParser.OPENBRAC), |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "n"))), |
| unaryExpression("x[n]")); |
| |
| Matches(List(Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "x")), |
| Node(CTFParser.OPENBRAC), |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "n")), |
| Node(CTFParser.OPENBRAC), |
| Node(CTFParser.UNARY_EXPRESSION_DEC, |
| Node(CTFParser.DECIMAL_LITERAL, "1"))), |
| unaryExpression("x[n][1]")); |
| |
| Matches(List(Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "x")), |
| Node(CTFParser.OPENBRAC), |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "n")), |
| Node(CTFParser.OPENBRAC), |
| Node(CTFParser.UNARY_EXPRESSION_DEC, |
| Node(CTFParser.DECIMAL_LITERAL, "1"), |
| Node(CTFParser.SIGN, "+"))), |
| unaryExpression("x[n][+1]")); |
| } |
| |
| /** |
| * Validate parsing array with keywords through an unary expression |
| */ |
| @Test |
| public void testSpecialArrayUnaryExpression() { |
| // Added for CTF-v1.8 |
| Matches(List(Node(CTFParser.TRACE), |
| Node(CTFParser.OPENBRAC), |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "n"))), |
| unaryExpression("trace[n]")); |
| |
| Matches(List(Node(CTFParser.CLOCK), |
| Node(CTFParser.OPENBRAC), |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "n")), |
| Node(CTFParser.OPENBRAC), |
| Node(CTFParser.UNARY_EXPRESSION_DEC, |
| Node(CTFParser.DECIMAL_LITERAL, "1"))), |
| unaryExpression("clock[n][1]")); |
| } |
| |
| /** |
| * Validate parsing member expression through an unary expression |
| */ |
| @Test |
| public void testMemberUnaryExpression() { |
| Matches(List(Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "x")), |
| Node(CTFParser.DOT, |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "y")))), |
| unaryExpression("x.y")); |
| |
| Matches(List(Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "x")), |
| Node(CTFParser.DOT, |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "y"))), |
| Node(CTFParser.DOT, |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "z")))), |
| unaryExpression("x.y.z")); |
| } |
| |
| /** |
| * Validate parsing pointer expression through an unary expression |
| */ |
| @Test |
| public void testPointerUnaryExpression() { |
| Matches(List(Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "x")), |
| Node(CTFParser.ARROW, |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "y")))), |
| unaryExpression("x->y")); |
| |
| Matches(List(Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "x")), |
| Node(CTFParser.ARROW, |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "y"))), |
| Node(CTFParser.ARROW, |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "z")))), |
| unaryExpression("x->y->z")); |
| } |
| |
| /** |
| * Validate complex expressions through an unary expression |
| */ |
| @Test |
| public void testMixedUnaryExpression() { |
| Matches(List(Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "x")), |
| Node(CTFParser.OPENBRAC), |
| Node(CTFParser.UNARY_EXPRESSION_DEC, |
| Node(CTFParser.DECIMAL_LITERAL, "2")), |
| Node(CTFParser.ARROW, |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "y"))), |
| Node(CTFParser.DOT, |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "z"))), |
| Node(CTFParser.OPENBRAC), |
| Node(CTFParser.UNARY_EXPRESSION_DEC, |
| Node(CTFParser.DECIMAL_LITERAL, "1"))), |
| unaryExpression("x[2]->y.z[1]")); |
| } |
| |
| /** |
| * Validate that parsing of an empty declaration is invalid. |
| */ |
| @Test |
| public void testDeclaration() { |
| CommonTree tree_empty = declaration(""); |
| assertEquals(null, tree_empty); |
| } |
| |
| /** |
| * Validate parsing of integer declaration |
| */ |
| @Test |
| public void testIntegerTypeAliasDeclaration() { |
| // TODO: replace the "all" match with a better tree matcher. |
| Matches(All(), |
| declaration("typealias integer { } := int;")); |
| Matches(All(), |
| declaration("typealias integer { signed=true; } := int;")); |
| } |
| |
| /** |
| * Validate parsing of floating declaration |
| */ |
| @Test |
| public void testFloatingTypeAliasDeclaration() { |
| // TODO: replace the "all" match with a better tree matcher. |
| Matches(All(), |
| declaration("typealias floating_point { } := float;")); |
| Matches(All(), |
| declaration("typealias floating_point { align = 32; } := float;")); |
| } |
| |
| /** |
| * Validate parsing of typedef declaration |
| */ |
| @Ignore("This need a fix to the grammar to support a dummy initial scope. ") |
| @Test |
| public void testTypedefDeclaration() { |
| // TODO: replace the "all" match with a better tree matcher. |
| Matches(All(), |
| declaration("typedef dummy int;")); |
| Matches(All(), |
| declaration("typedef integer { } int;")); |
| } |
| |
| /** |
| * Validate parsing of an enum declaration |
| */ |
| @Test |
| public void testEnumDeclaration() { |
| Matches(Node(CTFParser.DECLARATION, |
| Node(CTFParser.TYPE_SPECIFIER_LIST, |
| Node(CTFParser.ENUM, |
| Node(CTFParser.ENUM_NAME, |
| Node(CTFParser.IDENTIFIER, "name")), |
| Node(CTFParser.ENUM_BODY, |
| Node(CTFParser.ENUM_ENUMERATOR, |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "A"))))))), |
| declaration("enum name { A };")); |
| |
| Matches(Node(CTFParser.DECLARATION, |
| Node(CTFParser.TYPE_SPECIFIER_LIST, |
| Node(CTFParser.ENUM, |
| Node(CTFParser.ENUM_NAME, All()), |
| Node(CTFParser.ENUM_CONTAINER_TYPE, |
| Node(CTFParser.TYPE_SPECIFIER_LIST, |
| Node(CTFParser.INTTOK))), |
| Node(CTFParser.ENUM_BODY, All())))), |
| declaration("enum name : int { A };")); |
| |
| Matches(Node(CTFParser.DECLARATION, |
| Node(CTFParser.TYPE_SPECIFIER_LIST, |
| Node(CTFParser.ENUM, |
| Node(CTFParser.ENUM_BODY, All())))), |
| declaration("enum { A };")); |
| |
| Matches(Node(CTFParser.DECLARATION, |
| Node(CTFParser.TYPE_SPECIFIER_LIST, |
| Node(CTFParser.ENUM, |
| Node(CTFParser.ENUM_CONTAINER_TYPE, |
| Node(CTFParser.TYPE_SPECIFIER_LIST, |
| Node(CTFParser.INTTOK))), |
| Node(CTFParser.ENUM_BODY, All())))), |
| declaration("enum : int { A };")); |
| } |
| |
| /** |
| * Validate parsing of an enumerator |
| */ |
| @Ignore("The grammar needs to be fixed.") |
| @Test |
| public void testDeclaratorOfEnumDeclaration() { |
| /* TODO: This test crash the parser. */ |
| Matches(All(), |
| declaration("enum { };")); |
| |
| Matches(Node(CTFParser.DECLARATION, |
| Node(CTFParser.TYPE_SPECIFIER_LIST, |
| Node(CTFParser.ENUM, |
| Node(CTFParser.ENUM_BODY, |
| Node(CTFParser.ENUM_ENUMERATOR, |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "A"))), |
| Node(CTFParser.ENUM_ENUMERATOR, |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "B")), |
| Node(CTFParser.ENUM_VALUE, |
| Node(CTFParser.UNARY_EXPRESSION_DEC, |
| Node(CTFParser.DECIMAL_LITERAL, "2")))), |
| Node(CTFParser.ENUM_ENUMERATOR, |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "C")), |
| Node(CTFParser.ENUM_VALUE_RANGE, |
| Node(CTFParser.UNARY_EXPRESSION_DEC, |
| Node(CTFParser.DECIMAL_LITERAL, "3")), |
| Node(CTFParser.UNARY_EXPRESSION_DEC, |
| Node(CTFParser.DECIMAL_LITERAL, "5")))))))), |
| declaration("enum { A, B=2, C=3...5 };")); |
| |
| Matches(Node(CTFParser.DECLARATION, |
| Node(CTFParser.TYPE_SPECIFIER_LIST, |
| Node(CTFParser.ENUM, |
| Node(CTFParser.ENUM_BODY, |
| Node(CTFParser.ENUM_ENUMERATOR, |
| Node(CTFParser.UNARY_EXPRESSION_STRING_QUOTES, |
| Node(CTFParser.STRING_LITERAL, "\"A\""))), |
| Node(CTFParser.ENUM_ENUMERATOR, |
| Node(CTFParser.UNARY_EXPRESSION_STRING_QUOTES, |
| Node(CTFParser.STRING_LITERAL, "\"B\"")), |
| All()))))), |
| declaration("enum { \"A\", \"B\"=2 };")); |
| } |
| |
| /** |
| * Validate parsing of empty declaration |
| */ |
| @Ignore("The grammar need to be fixed to support empty ctf-body.") |
| @Test |
| public void testEmptyDeclaration() { |
| /* |
| * TODO: An exception is throw when building an common tree without |
| * assignments in the ctf-body. |
| */ |
| Matches(All(), |
| declaration("env { };")); |
| Matches(All(), |
| declaration("trace { };")); |
| Matches(All(), |
| declaration("stream { };")); |
| Matches(All(), |
| declaration("event { };")); |
| } |
| |
| /** |
| * Validate parsing of an environment declaration |
| */ |
| @Test |
| public void testEnvDeclaration() { |
| Matches(Node(CTFParser.ENV, |
| Node(CTFParser.CTF_EXPRESSION_VAL, |
| Node(CTFParser.CTF_LEFT, |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "pid"))), |
| Node(CTFParser.CTF_RIGHT, |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "value"))))), |
| declaration("env { pid = value; };")); |
| |
| Matches(Node(CTFParser.ENV, |
| Node(CTFParser.CTF_EXPRESSION_VAL, All(), All()), |
| Node(CTFParser.CTF_EXPRESSION_VAL, All(), All()), |
| Node(CTFParser.CTF_EXPRESSION_VAL, All(), All())), |
| declaration("env { pid = value; proc_name = \"name\"; x = y;};")); |
| } |
| |
| /** |
| * Validate parsing of a trace declaration |
| */ |
| @Ignore("The grammar need to be fixed.") |
| @Test |
| public void testTraceDeclaration() { |
| Matches(Node(CTFParser.TRACE, |
| Node(CTFParser.CTF_EXPRESSION_VAL, |
| Node(CTFParser.CTF_LEFT, |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "major"))), |
| Node(CTFParser.CTF_RIGHT, |
| Node(CTFParser.UNARY_EXPRESSION_DEC, |
| Node(CTFParser.DECIMAL_LITERAL, "1"))))), |
| declaration("trace { major = 1; };")); |
| |
| Matches(Node(CTFParser.TRACE, |
| Node(CTFParser.CTF_EXPRESSION_TYPE, |
| Node(CTFParser.CTF_LEFT, |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "packet")), |
| Node(CTFParser.DOT, |
| Node(CTFParser.UNARY_EXPRESSION_STRING, |
| Node(CTFParser.IDENTIFIER, "header")))), |
| Node(CTFParser.CTF_RIGHT, |
| Node(CTFParser.TYPE_SPECIFIER_LIST, |
| Node(CTFParser.STRUCT, |
| Node(CTFParser.STRUCT_NAME, |
| Node(CTFParser.IDENTIFIER, "dummy"))))))), |
| declaration("trace { packet.header := struct dummy; };")); |
| |
| /* TODO: This test crash the parser. */ |
| Matches(Node(CTFParser.TRACE, |
| All()), |
| declaration("trace { typedef x y; };")); |
| |
| Matches(Node(CTFParser.TRACE, |
| Node(CTFParser.CTF_EXPRESSION_VAL, All(), All()), |
| Node(CTFParser.CTF_EXPRESSION_VAL, All(), All()), |
| Node(CTFParser.CTF_EXPRESSION_TYPE, All(), All())), |
| declaration("trace { major = 1; minor = 1;" |
| + "packet.header := struct dummy; };")); |
| } |
| |
| } |