ctf: split up IOStructGen into 44 files
authorMatthew Khouzam <matthew.khouzam@ericsson.com>
Sat, 29 Aug 2015 19:53:47 +0000 (15:53 -0400)
committerMatthew Khouzam <matthew.khouzam@ericsson.com>
Thu, 14 Jan 2016 19:43:41 +0000 (14:43 -0500)
IOstructGen is a very large file, it is hard to test and maintain, this patch
splits it into 42 files.

This patch has several benefits. It does the following:
* decreases the complexity of the file IOStructGen.
* improves the modularity of the TSDL parser.
* is very friendly to code navigators as the links of who calls who
    are more obvious.
* improve testability of the parser.
* improve navigability in code.
* use a single pattern so each section is drop-in replaceable.
* add null checks at strategic places.
* ridiculously improve javadoc.
* add null annotations
* improve validation of data

Performance is similar.

Change-Id: Ie13ab1673d40b36087e7ce78d81b5379063ea3a1
Signed-off-by: Matthew Khouzam <matthew.khouzam@ericsson.com>
Reviewed-on: https://git.eclipse.org/r/56740
Reviewed-by: Hudson CI
Reviewed-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
Tested-by: Marc-Andre Laperle <marc-andre.laperle@ericsson.com>
74 files changed:
common/org.eclipse.tracecompass.common.core/annotations/java/lang/String.eea
common/org.eclipse.tracecompass.common.core/annotations/java/util/List.eea [new file with mode: 0644]
common/org.eclipse.tracecompass.common.core/annotations/java/util/UUID.eea [new file with mode: 0644]
common/org.eclipse.tracecompass.common.core/annotations/org/antlr/runtime/tree/BaseTree.eea [new file with mode: 0644]
common/org.eclipse.tracecompass.common.core/annotations/org/antlr/runtime/tree/CommonTree.eea [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core.tests/src/org/eclipse/tracecompass/ctf/core/tests/trace/CTFStreamTest.java
ctf/org.eclipse.tracecompass.ctf.core.tests/src/org/eclipse/tracecompass/ctf/core/tests/trace/CTFTraceTest.java
ctf/org.eclipse.tracecompass.ctf.core/META-INF/MANIFEST.MF
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/metadata/DeclarationScope.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/event/types/EnumDeclaration.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/CTFTrace.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/ctf/core/trace/Metadata.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/AbstractScopedCommonTreeParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/CtfAntlrException.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/ICommonTreeParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/IOStructGen.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/Messages.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/MetadataStrings.java
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/ParseException.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/exceptions/CtfAntlrException.java [deleted file]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/exceptions/ParseException.java [deleted file]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/messages.properties
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/AlignmentParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/ByteOrderParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/ClockParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/PointerListStringParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/SizeParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TsdlUtils.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeAliasAliasParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeAliasParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeAliasTargetParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeDeclarationParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeDeclarationStringParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeDeclaratorParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeSpecifierListNameParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeSpecifierListParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeSpecifierListStringParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypedefParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/UnaryIntegerParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/UnaryStringParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/enumeration/EnumBodyParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/enumeration/EnumContainerParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/enumeration/EnumParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/enumeration/EnumeratorParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/environment/EnvironmentParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/event/EventDeclarationParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/event/EventIDParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/event/EventNameParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/event/EventParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/event/EventScopeParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/floatingpoint/FloatDeclarationParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/integer/BaseParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/integer/ClockMapParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/integer/IntegerDeclarationParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/integer/SignedParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/stream/StreamDeclarationParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/stream/StreamIdParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/stream/StreamParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/stream/StreamScopeParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/string/EncodingParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/string/StringDeclarationParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/struct/StructBodyParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/struct/StructDeclarationParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/struct/StructParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/trace/TraceDeclarationParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/trace/TraceScopeParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/trace/UUIDParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/trace/VersionNumberParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/variant/VariantBodyParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/variant/VariantDeclarationParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/variant/VariantParser.java [new file with mode: 0644]
ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/trace/CTFStream.java
ctf/org.eclipse.tracecompass.ctf.parser.tests/src/org/eclipse/tracecompass/ctf/parser/tests/CtfParserTest.java
ctf/org.eclipse.tracecompass.tmf.ctf.ui.swtbot.tests/src/org/eclipse/tracecompass/tmf/ctf/ui/swtbot/tests/TestInvalidCtfTrace.java

index d08937251cb59c19618c6cc01df6041650e2f952..73b41b1f8a9527d3131e9479d031ca9fd6ca70c1 100644 (file)
@@ -20,6 +20,9 @@ split
 split
  (Ljava/lang/String;I)[Ljava/lang/String;
  (L1java/lang/String;I)[1L1java/lang/String;
+substring
+ (II)Ljava/lang/String;
+ (II)L1java/lang/String;
 toString
  ()Ljava/lang/String;
  ()L1java/lang/String;
diff --git a/common/org.eclipse.tracecompass.common.core/annotations/java/util/List.eea b/common/org.eclipse.tracecompass.common.core/annotations/java/util/List.eea
new file mode 100644 (file)
index 0000000..dd035af
--- /dev/null
@@ -0,0 +1,4 @@
+class java/util/List
+subList
+ (II)Ljava/util/List<TE;>;
+ (II)L1java/util/List<TE;>;
diff --git a/common/org.eclipse.tracecompass.common.core/annotations/java/util/UUID.eea b/common/org.eclipse.tracecompass.common.core/annotations/java/util/UUID.eea
new file mode 100644 (file)
index 0000000..116f7ff
--- /dev/null
@@ -0,0 +1,19 @@
+class java/util/UUID
+UUID
+ ([B)V
+ ([1B)V
+digits
+ (JI)Ljava/lang/String;
+ (JI)L1java/lang/String;
+fromString
+ (Ljava/lang/String;)Ljava/util/UUID;
+ (L1java/lang/String;)L1java/util/UUID;
+nameUUIDFromBytes
+ ([B)Ljava/util/UUID;
+ ([1B)L1java/util/UUID;
+randomUUID
+ ()Ljava/util/UUID;
+ ()L1java/util/UUID;
+toString
+ ()Ljava/lang/String;
+ ()L1java/lang/String;
diff --git a/common/org.eclipse.tracecompass.common.core/annotations/org/antlr/runtime/tree/BaseTree.eea b/common/org.eclipse.tracecompass.common.core/annotations/org/antlr/runtime/tree/BaseTree.eea
new file mode 100644 (file)
index 0000000..c3e0b19
--- /dev/null
@@ -0,0 +1,4 @@
+class org/antlr/runtime/tree/BaseTree
+getFirstChildWithType
+ (I)Lorg/antlr/runtime/tree/Tree;
+ (I)L0org/antlr/runtime/tree/Tree;
diff --git a/common/org.eclipse.tracecompass.common.core/annotations/org/antlr/runtime/tree/CommonTree.eea b/common/org.eclipse.tracecompass.common.core/annotations/org/antlr/runtime/tree/CommonTree.eea
new file mode 100644 (file)
index 0000000..279e458
--- /dev/null
@@ -0,0 +1,7 @@
+class org/antlr/runtime/tree/CommonTree
+dupNode
+ ()Lorg/antlr/runtime/tree/Tree;
+ ()L1org/antlr/runtime/tree/Tree;
+getText
+ ()Ljava/lang/String;
+ ()L0java/lang/String;
\ No newline at end of file
index 6c29917134c2665cea0bae30cb2ea76000f1b6e0..e9b3202eee277383f756bc352aedb593952991ea 100644 (file)
@@ -26,7 +26,7 @@ import org.eclipse.tracecompass.ctf.core.tests.shared.CtfTestTraceUtils;
 import org.eclipse.tracecompass.ctf.core.trace.CTFStreamInput;
 import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
 import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
-import org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
 import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
 import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
 import org.junit.Before;
index fa9b59fe1ba4a2fed546dd1e35008bd101fd3778..8a4dfd2762574100b42adcc9cd39354779091c50 100644 (file)
@@ -31,12 +31,14 @@ import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
 import org.eclipse.tracecompass.ctf.core.tests.shared.CtfTestTraceUtils;
 import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
 import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
-import org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
 import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
 import org.eclipse.tracecompass.testtraces.ctf.CtfTestTrace;
 import org.junit.Before;
 import org.junit.Test;
 
+import com.google.common.collect.ImmutableMap;
+
 /**
  * The class <code>CTFTraceTest</code> contains tests for the class
  * <code>{@link CTFTrace}</code>.
@@ -370,10 +372,10 @@ public class CTFTraceTest {
     @Test
     public void testLookupEnvironment_3() {
         String key = "test";
-        fixture.addEnvironmentVar(key, key);
+        fixture.setEnvironment(ImmutableMap.<String, String> of(key, key));
         String result = fixture.getEnvironment().get(key);
         assertNotNull(result);
-        assertTrue(result.equals(key));
+        assertEquals(key, result);
     }
 
     /**
@@ -382,8 +384,7 @@ public class CTFTraceTest {
     @Test
     public void testLookupEnvironment_4() {
         String key = "test";
-        fixture.addEnvironmentVar(key, "bozo");
-        fixture.addEnvironmentVar(key, "the clown");
+        fixture.setEnvironment(ImmutableMap.<String, String> of(key, "bozo"));
         String result = fixture.getEnvironment().get(key);
         assertNotNull(result);
     }
index 3163cac192aff0e8c6887d30218cb5ccec460940..99dcd377eef0bca077bc9528b4e241479c402530 100644 (file)
@@ -21,7 +21,17 @@ Export-Package: org.eclipse.tracecompass.ctf.core,
  org.eclipse.tracecompass.internal.ctf.core;x-friends:="org.eclipse.tracecompass.ctf.core.tests",
  org.eclipse.tracecompass.internal.ctf.core.event;x-friends:="org.eclipse.tracecompass.ctf.core.tests",
  org.eclipse.tracecompass.internal.ctf.core.event.metadata;x-friends:="org.eclipse.tracecompass.ctf.core.tests",
- org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions;x-friends:="org.eclipse.tracecompass.ctf.core.tests",
+ org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl;x-friends:="org.eclipse.tracecompass.ctf.core.tests",
+ org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.enumeration;x-friends:="org.eclipse.tracecompass.ctf.core.tests",
+ org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.environment;x-friends:="org.eclipse.tracecompass.ctf.core.tests",
+ org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.event;x-friends:="org.eclipse.tracecompass.ctf.core.tests",
+ org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.floatingpoint;x-friends:="org.eclipse.tracecompass.ctf.core.tests",
+ org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.integer;x-friends:="org.eclipse.tracecompass.ctf.core.tests",
+ org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.stream;x-friends:="org.eclipse.tracecompass.ctf.core.tests",
+ org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.string;x-friends:="org.eclipse.tracecompass.ctf.core.tests",
+ org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.struct;x-friends:="org.eclipse.tracecompass.ctf.core.tests",
+ org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.trace;x-friends:="org.eclipse.tracecompass.ctf.core.tests",
+ org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.variant;x-friends:="org.eclipse.tracecompass.ctf.core.tests",
  org.eclipse.tracecompass.internal.ctf.core.event.types;x-friends:="org.eclipse.tracecompass.ctf.core.tests,org.eclipse.tracecompass.tmf.ctf.core,org.eclipse.tracecompass.tmf.ctf.core.tests",
  org.eclipse.tracecompass.internal.ctf.core.event.types.composite;x-friends:="org.eclipse.tracecompass.ctf.core.tests",
  org.eclipse.tracecompass.internal.ctf.core.trace;x-friends:="org.eclipse.tracecompass.ctf.core.tests"
index fb0deeb916bb53fd5dfe0e11294c15d6d05dc598..d0fe08fb9ef30327d25eaf1c3239ca86f926fcc2 100644 (file)
@@ -23,7 +23,7 @@ import org.eclipse.tracecompass.ctf.core.event.types.EnumDeclaration;
 import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
 import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
 import org.eclipse.tracecompass.ctf.core.event.types.VariantDeclaration;
-import org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
 
 /**
  * <b><u>DeclarationScope</u></b>
@@ -543,4 +543,9 @@ public class DeclarationScope {
         fChildren.put(scope.fName, scope);
         scope.fParentScope = this;
     }
+
+    @Override
+    public String toString() {
+        return "Scope : " + fName + " children: " + fChildren.size() + (fParentScope == null ? "" : (" parent " + fParentScope.fName)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
+    }
 }
index 77238602f31d0a3e347429125aec9f20ebcaa489..30155e142f356d37b53c5e5bbc6dea1e2eb76491 100644 (file)
@@ -161,6 +161,20 @@ public final class EnumDeclaration extends Declaration implements ISimpleDatatyp
         return fTable.add(low, high, label);
     }
 
+    /**
+     * Add a value. Do not overlap, this is <em><strong>not</strong></em> an
+     * interval tree. This could be seen more as a collection of segments.
+     *
+     * @param label
+     *            the name of the value.
+     * @return was the value be added? true == success
+     * @since 2.0
+     */
+    public boolean add(@Nullable String label) {
+        fLabels.add(label);
+        return fTable.add(label);
+    }
+
     /**
      * Check if the label for a value (enum a{day=0,night=1} would return "day"
      * for query(0)
@@ -208,6 +222,11 @@ public final class EnumDeclaration extends Declaration implements ISimpleDatatyp
         public EnumTable() {
         }
 
+        public synchronized boolean add(@Nullable String label) {
+            LabelAndRange lastAdded = ranges.isEmpty() ? new LabelAndRange(-1, -1, "") : ranges.get(ranges.size() - 1); //$NON-NLS-1$
+            return add(lastAdded.low + 1, lastAdded.high + 1, label);
+        }
+
         public synchronized boolean add(long low, long high, @Nullable String label) {
             LabelAndRange newRange = new LabelAndRange(low, high, label);
 
index e44ad4a9f02ebc0714dacf6ba9e1a56c5ca9d0a8..5053c34dedd64bb64d07fda17cb1c2cb96c85e1c 100644 (file)
@@ -32,6 +32,7 @@ import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 
+import org.eclipse.jdt.annotation.NonNull;
 import org.eclipse.tracecompass.ctf.core.CTFException;
 import org.eclipse.tracecompass.ctf.core.CTFStrings;
 import org.eclipse.tracecompass.ctf.core.event.CTFClock;
@@ -48,10 +49,12 @@ import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
 import org.eclipse.tracecompass.ctf.core.event.types.StructDefinition;
 import org.eclipse.tracecompass.internal.ctf.core.SafeMappedByteBuffer;
 import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
-import org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
 import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
 import org.eclipse.tracecompass.internal.ctf.core.trace.Utils;
 
+import com.google.common.collect.ImmutableMap;
+
 /**
  * A CTF trace on the file system.
  *
@@ -125,7 +128,7 @@ public class CTFTrace implements IDefinitionScope {
     /**
      * Collection of environment variables set by the tracer
      */
-    private final Map<String, String> fEnvironment = new HashMap<>();
+    private Map<String, String> fEnvironment = new HashMap<>();
 
     /**
      * Collection of all the clocks in a system.
@@ -632,18 +635,6 @@ public class CTFTrace implements IDefinitionScope {
         return Collections.unmodifiableMap(fEnvironment);
     }
 
-    /**
-     * Add a variable to the environment variables
-     *
-     * @param varName
-     *            the name of the variable
-     * @param varValue
-     *            the value of the variable
-     */
-    public void addEnvironmentVar(String varName, String varValue) {
-        fEnvironment.put(varName, varValue);
-    }
-
     /**
      * Add a clock to the clock list
      *
@@ -847,6 +838,17 @@ public class CTFTrace implements IDefinitionScope {
     public StructDefinition getPacketHeaderDef() {
         return fPacketHeaderDef;
     }
+
+    /**
+     * Sets the environment map
+     *
+     * @param parseEnvironment
+     *            The environment map
+     * @since 2.0
+     */
+    public void setEnvironment(@NonNull Map<String, String> parseEnvironment) {
+        fEnvironment = ImmutableMap.copyOf(parseEnvironment);
+    }
 }
 
 class MetadataFileFilter implements FileFilter {
index 3f054defd1309bb3f7a61617cdf57a5a680a0397..df4e97c591198985fcde5608f4241417180be3e1 100644 (file)
@@ -37,13 +37,14 @@ import org.antlr.runtime.CommonTokenStream;
 import org.antlr.runtime.RecognitionException;
 import org.antlr.runtime.tree.CommonTree;
 import org.antlr.runtime.tree.RewriteCardinalityException;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
 import org.eclipse.tracecompass.ctf.core.CTFException;
 import org.eclipse.tracecompass.ctf.parser.CTFLexer;
 import org.eclipse.tracecompass.ctf.parser.CTFParser;
 import org.eclipse.tracecompass.ctf.parser.CTFParser.parse_return;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.CtfAntlrException;
 import org.eclipse.tracecompass.internal.ctf.core.event.metadata.IOStructGen;
-import org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.CtfAntlrException;
-import org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
 import org.eclipse.tracecompass.internal.ctf.core.trace.Utils;
 
 /**
@@ -154,10 +155,7 @@ public class Metadata {
         try (FileInputStream fis = new FileInputStream(getMetadataPath());
                 FileChannel metadataFileChannel = fis.getChannel();
                 /* Check if metadata is packet-based, if not it is text based */
-                Reader metadataTextInput =
-                        (isPacketBased(metadataFileChannel) ?
-                                readBinaryMetaData(metadataFileChannel) :
-                                new FileReader(getMetadataPath()));) {
+                Reader metadataTextInput = (isPacketBased(metadataFileChannel) ? readBinaryMetaData(metadataFileChannel) : new FileReader(getMetadataPath()));) {
 
             readMetaDataText(metadataTextInput);
 
@@ -190,10 +188,14 @@ public class Metadata {
     }
 
     /**
-     * Executes a weak validation of the metadata. It checks if a file with
-     * name metadata exists and if one of the following conditions are met:
-     * - For text-only metadata, the file starts with "/* CTF" (without the quotes)
-     * - For packet-based metadata, the file starts with correct magic number
+     * Executes a weak validation of the metadata. It checks if a file with name
+     * metadata exists and if one of the following conditions are met:
+     * <ul>
+     * <li>For text-only metadata, the file starts with "/* CTF" (without the
+     * quotes)</li>
+     * <li>For packet-based metadata, the file starts with correct magic number
+     * </li>
+     * </ul>
      *
      * @param path
      *            path to CTF trace directory
@@ -257,7 +259,7 @@ public class Metadata {
         CommonTree tree = createAST(metadataTextInput);
 
         /* Generate IO structures (declarations) */
-        fTreeParser = new IOStructGen(tree, fTrace);
+        fTreeParser = new IOStructGen(tree, NonNullUtils.checkNotNull(fTrace));
         fTreeParser.generate();
         /* store locally in case of concurrent modification */
         ByteOrder detectedByteOrder = getDetectedByteOrder();
@@ -377,7 +379,7 @@ public class Metadata {
      */
     private MetadataPacketHeader readMetadataPacket(
             FileChannel metadataFileChannel, StringBuffer metadataText)
-            throws CTFException {
+                    throws CTFException {
         /* Allocate a ByteBuffer for the header */
         ByteBuffer headerByteBuffer = ByteBuffer.allocate(METADATA_PACKET_HEADER_SIZE);
 
@@ -513,8 +515,9 @@ public class Metadata {
 
     /**
      * Copies the metadata file to a destination directory.
+     *
      * @param path
-     *             the destination directory
+     *            the destination directory
      * @return the path to the target file
      * @throws IOException
      *             if an error occurred
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/AbstractScopedCommonTreeParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/AbstractScopedCommonTreeParser.java
new file mode 100644 (file)
index 0000000..90b754b
--- /dev/null
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata;
+
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
+import org.eclipse.tracecompass.ctf.core.event.types.EnumDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.VariantDeclaration;
+
+/**
+ * Common tree parser with scopes
+ *
+ * @author Matthew Khouzam
+ *
+ */
+@NonNullByDefault
+public abstract class AbstractScopedCommonTreeParser implements ICommonTreeParser {
+
+    /**
+     * Register a declaration to the current scope
+     *
+     * @param declaration
+     *            the declaration to register
+     * @param identifier
+     *            the declaration's name
+     * @param scope the scope to register
+     * @throws ParseException
+     *             if something already has that name
+     */
+    protected void registerType(IDeclaration declaration, String identifier , DeclarationScope scope) throws ParseException {
+        if (declaration instanceof EnumDeclaration) {
+            if (scope.lookupEnum(identifier) == null) {
+                scope.registerEnum(identifier, (EnumDeclaration) declaration);
+            }
+        } else if (declaration instanceof VariantDeclaration) {
+            scope.registerVariant(identifier, (VariantDeclaration) declaration);
+        }
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/CtfAntlrException.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/CtfAntlrException.java
new file mode 100644 (file)
index 0000000..101aa41
--- /dev/null
@@ -0,0 +1,134 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2015 Ericsson
+ *
+ * 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:
+ *   Alexandre Montplaisir - Initial API and implementation
+ *   Matthew Khouzam - Addition to have more descriptive errors
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata;
+
+import java.lang.reflect.Field;
+
+import org.antlr.runtime.MismatchedTokenException;
+import org.antlr.runtime.RecognitionException;
+import org.eclipse.tracecompass.ctf.core.CTFException;
+import org.eclipse.tracecompass.ctf.parser.CTFLexer;
+
+/**
+ * CTF Reader exception but dealing with Antlr-specific parsing problems.
+ *
+ * It is separated from the main {@link CTFException} - and is not part of the
+ * API - to isolate the Antlr-specific classes and avoid pushing that dependency
+ * to the users of this plugin.
+ *
+ * @author Matthew Khouzam
+ */
+public class CtfAntlrException extends CTFException {
+
+    private static final long serialVersionUID = -7078624493350073777L;
+
+    private final int fErrorLine;
+    private final String fFile;
+    private String fExpectingName = ""; //$NON-NLS-1$
+    private int fExpectedValue = -1;
+    private String fActualName = ""; //$NON-NLS-1$
+    private int fActualValue = -1;
+
+    private final int fCharPositionInLine;
+
+    /**
+     * Re-throw the exception but read its data
+     *
+     * @param e
+     *            the previous recognition exception (Antlr specific)
+     */
+    public CtfAntlrException(MismatchedTokenException e) {
+        super(e);
+        fErrorLine = e.line;
+        fCharPositionInLine = e.charPositionInLine;
+        fFile = "metadata"; //$NON-NLS-1$ // we're in CTF, the only thing using antlr is metadata
+        parseMismatchedException(e);
+    }
+
+    /**
+     * Re-throw the exception but read its data
+     *
+     * @param e
+     *            the previous recognition exception (Antlr specific)
+     */
+    public CtfAntlrException(RecognitionException e) {
+        super(e);
+        fErrorLine = e.line;
+        fCharPositionInLine = e.charPositionInLine;
+        fFile = "metadata"; //$NON-NLS-1$ // we're in CTF, the only thing using antlr is metadata
+    }
+
+    /**
+     * Re-throw the exception but read its data
+     *
+     * @param e
+     *            the previous rewrite exception (Antlr specific)
+     */
+    public CtfAntlrException(Exception e) {
+        super(e);
+        fErrorLine = -1;
+        fCharPositionInLine = -1;
+        fFile = "metadata"; //$NON-NLS-1$ // we're in CTF, the only thing using antlr is metadata
+    }
+
+    private void parseMismatchedException(MismatchedTokenException m) {
+        // Iterate through the tokens that are hidden in the CTFLexer
+        // They are private static final int fields.
+        for (Field f : CTFLexer.class.getDeclaredFields()) {
+            f.setAccessible(true);
+            String name;
+            int value;
+            try {
+                name = f.getName();
+                final boolean isInt = (f.getType().isPrimitive());
+                if (isInt) {
+                    value = ((Integer) f.get(null)).intValue();
+                    if (value == m.expecting) {
+                        this.fExpectingName = name;
+                        this.fExpectedValue = value;
+                    }
+                    if (value == m.c) {
+                        this.fActualName = name;
+                        this.fActualValue = value;
+                    }
+                }
+            } catch (NullPointerException e1) {
+                // Pokemon, gotta catch em all!
+                // actually useful since f may not have a
+                // value
+            } catch (IllegalArgumentException e1) {
+                // Catch these exceptions (reflexion)
+            } catch (IllegalAccessException e1) {
+                // Catch these exceptions (reflexion)
+            }
+            if (!this.fExpectingName.isEmpty() && !this.fActualName.isEmpty()) {
+                return;
+            }
+        }
+    }
+
+    @Override
+    public String getMessage() {
+        final String message = super.getMessage();
+        if (fErrorLine == -1) {
+            return message;
+        }
+        String expected = "" + this.fExpectedValue; //$NON-NLS-1$
+        String actual = "" + this.fActualValue; //$NON-NLS-1$
+        String newMessage = message.replaceAll(expected, this.fExpectingName);
+        newMessage = newMessage.replaceAll(actual, this.fActualName);
+        return newMessage + " at " + fFile + ":" + fErrorLine + ":" + fCharPositionInLine; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/ICommonTreeParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/ICommonTreeParser.java
new file mode 100644 (file)
index 0000000..ba46d7f
--- /dev/null
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNull;
+
+/**
+ * Common tree parser interface. Should only have one method
+ * {@link #parse(CommonTree, ICommonTreeParserParameter)}
+ *
+ * It is recommended to add to the javadoc on this inerface as it is not
+ * specific
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public interface ICommonTreeParser {
+
+    /**
+     * Parameter object to avoid passing "Object" as a parameter
+     * @author Matthew Khouzam
+     *
+     */
+    public interface ICommonTreeParserParameter{
+
+    }
+
+    /**
+     * The only parse method of the common tree parser. Caution must be used
+     * handling this as it can return any type and thus care must be used with
+     * the input and output.
+     *
+     *
+     * @param tree
+     *            the common tree input
+     * @param param
+     *            the parameter to pass (for lookups)
+     * @return the parsed data
+     * @throws ParseException
+     *             if the tree or data is wrong
+     */
+    @NonNull
+    Object parse(CommonTree tree, ICommonTreeParserParameter param) throws ParseException;
+
+}
index bd7c26dc3b0f051733d949212baefadbfae1a313..839bcd55a16ba819ccf225751297a97e022e62b0 100644 (file)
 
 package org.eclipse.tracecompass.internal.ctf.core.event.metadata;
 
-import java.math.BigInteger;
-import java.nio.ByteOrder;
 import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.UUID;
 
 import org.antlr.runtime.tree.CommonTree;
-import org.antlr.runtime.tree.Tree;
-import org.eclipse.core.runtime.IStatus;
 import org.eclipse.jdt.annotation.NonNull;
-import org.eclipse.jdt.annotation.Nullable;
-import org.eclipse.tracecompass.ctf.core.CTFStrings;
+import org.eclipse.tracecompass.common.core.NonNullUtils;
 import org.eclipse.tracecompass.ctf.core.event.CTFClock;
 import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
-import org.eclipse.tracecompass.ctf.core.event.types.Encoding;
-import org.eclipse.tracecompass.ctf.core.event.types.EnumDeclaration;
-import org.eclipse.tracecompass.ctf.core.event.types.EnumDeclaration.Pair;
-import org.eclipse.tracecompass.ctf.core.event.types.FloatDeclaration;
-import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
-import org.eclipse.tracecompass.ctf.core.event.types.IEventHeaderDeclaration;
-import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
-import org.eclipse.tracecompass.ctf.core.event.types.StringDeclaration;
-import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
-import org.eclipse.tracecompass.ctf.core.event.types.VariantDeclaration;
 import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
-import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
 import org.eclipse.tracecompass.ctf.parser.CTFParser;
-import org.eclipse.tracecompass.internal.ctf.core.Activator;
-import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
-import org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException;
-import org.eclipse.tracecompass.internal.ctf.core.event.types.ArrayDeclaration;
-import org.eclipse.tracecompass.internal.ctf.core.event.types.SequenceDeclaration;
-import org.eclipse.tracecompass.internal.ctf.core.event.types.StructDeclarationFlattener;
-import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderCompactDeclaration;
-import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderLargeDeclaration;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.ClockParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TypeAliasParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TypeSpecifierListParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TypedefParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.environment.EnvironmentParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.event.EventParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.stream.StreamParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.trace.TraceDeclarationParser;
 import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
 
 import com.google.common.collect.Iterables;
@@ -69,31 +45,16 @@ public class IOStructGen {
     // Attributes
     // ------------------------------------------------------------------------
 
-    private static final @NonNull String MAP = "map"; //$NON-NLS-1$
-    private static final @NonNull String ENCODING = "encoding"; //$NON-NLS-1$
-    private static final @NonNull String BASE = "base"; //$NON-NLS-1$
-    private static final @NonNull String SIZE = "size"; //$NON-NLS-1$
-    private static final @NonNull String SIGNED = "signed"; //$NON-NLS-1$
-    private static final @NonNull String EMPTY_STRING = ""; //$NON-NLS-1$
-    private static final int INTEGER_BASE_16 = 16;
-    private static final int INTEGER_BASE_10 = 10;
-    private static final int INTEGER_BASE_8 = 8;
-    private static final int INTEGER_BASE_2 = 2;
-    private static final long DEFAULT_ALIGNMENT = 1;
-    private static final int DEFAULT_FLOAT_EXPONENT = 8;
-    private static final int DEFAULT_FLOAT_MANTISSA = 24;
-    private static final int DEFAULT_INT_BASE = 10;
     /**
      * The trace
      */
-    private final CTFTrace fTrace;
+    private final @NonNull CTFTrace fTrace;
     private CommonTree fTree;
 
     /**
      * The current declaration scope.
      */
-    private final DeclarationScope fRoot;
-    private DeclarationScope fScope;
+    private final @NonNull DeclarationScope fRoot;
 
     /**
      * Data helpers needed for streaming
@@ -113,11 +74,10 @@ public class IOStructGen {
      * @param trace
      *            the trace containing the places to put all the read metadata
      */
-    public IOStructGen(CommonTree tree, CTFTrace trace) {
+    public IOStructGen(CommonTree tree, @NonNull CTFTrace trace) {
         fTrace = trace;
         fTree = tree;
-        fRoot = trace.getScope();
-        fScope = fRoot;
+        fRoot = NonNullUtils.checkNotNull(trace.getScope());
     }
 
     /**
@@ -170,7 +130,6 @@ public class IOStructGen {
         CommonTree traceNode = null;
         boolean hasStreams = false;
         List<CommonTree> events = new ArrayList<>();
-        resetScope();
         for (CommonTree child : children) {
             final int type = child.getType();
             switch (type) {
@@ -185,17 +144,19 @@ public class IOStructGen {
                 parseTrace(traceNode);
                 break;
             case CTFParser.STREAM:
-                parseStream(child);
+                StreamParser.INSTANCE.parse(child, new StreamParser.Param(fTrace, fRoot));
                 hasStreams = true;
                 break;
             case CTFParser.EVENT:
                 events.add(child);
                 break;
             case CTFParser.CLOCK:
-                parseClock(child);
+                CTFClock ctfClock = ClockParser.INSTANCE.parse(child, null);
+                String nameValue = ctfClock.getName();
+                fTrace.addClock(nameValue, ctfClock);
                 break;
             case CTFParser.ENV:
-                parseEnvironment(child);
+                fTrace.setEnvironment(EnvironmentParser.INSTANCE.parse(child, null));
                 break;
             default:
                 throw childTypeError(child);
@@ -205,7 +166,6 @@ public class IOStructGen {
             throw new ParseException("Missing trace block"); //$NON-NLS-1$
         }
         parseEvents(events, hasStreams);
-        popScope();
         fHasBeenParsed = true;
     }
 
@@ -215,7 +175,7 @@ public class IOStructGen {
             fTrace.addStream(new CTFStream(fTrace));
         }
         for (CommonTree event : events) {
-            parseEvent(event);
+            EventParser.INSTANCE.parse(event, new EventParser.Param(fTrace, fRoot));
         }
     }
 
@@ -225,7 +185,6 @@ public class IOStructGen {
         }
         List<CommonTree> children = root.getChildren();
         List<CommonTree> events = new ArrayList<>();
-        resetScope();
         for (CommonTree child : children) {
             final int type = child.getType();
             switch (type) {
@@ -235,98 +194,45 @@ public class IOStructGen {
             case CTFParser.TRACE:
                 throw new ParseException("Trace block defined here, please use generate and not generateFragment to parse this fragment"); //$NON-NLS-1$
             case CTFParser.STREAM:
-                parseStream(child);
+                StreamParser.INSTANCE.parse(child, new StreamParser.Param(fTrace, fRoot));
                 break;
             case CTFParser.EVENT:
                 events.add(child);
                 break;
             case CTFParser.CLOCK:
-                parseClock(child);
+                CTFClock ctfClock = ClockParser.INSTANCE.parse(child, null);
+                String nameValue = ctfClock.getName();
+                fTrace.addClock(nameValue, ctfClock);
                 break;
             case CTFParser.ENV:
-                parseEnvironment(child);
+                fTrace.setEnvironment(EnvironmentParser.INSTANCE.parse(child, null));
                 break;
             default:
                 throw childTypeError(child);
             }
         }
         parseEvents(events, !Iterables.isEmpty(fTrace.getStreams()));
-        popScope();
-    }
-
-    private void resetScope() {
-        fScope = fRoot;
-    }
-
-    private void parseEnvironment(CommonTree environment) {
-        List<CommonTree> children = environment.getChildren();
-        for (CommonTree child : children) {
-            String left;
-            String right;
-            left = child.getChild(0).getChild(0).getChild(0).getText();
-            right = child.getChild(1).getChild(0).getChild(0).getText();
-            fTrace.addEnvironmentVar(left, right);
-        }
-    }
-
-    private void parseClock(CommonTree clock) throws ParseException {
-        List<CommonTree> children = clock.getChildren();
-        CTFClock ctfClock = new CTFClock();
-        for (CommonTree child : children) {
-            final String key = child.getChild(0).getChild(0).getChild(0).getText();
-            final CommonTree value = (CommonTree) child.getChild(1).getChild(0).getChild(0);
-            final int type = value.getType();
-            final String text = value.getText();
-            switch (type) {
-            case CTFParser.INTEGER:
-            case CTFParser.DECIMAL_LITERAL:
-                /*
-                 * Not a pretty hack, this is to make sure that there is no
-                 * number overflow due to 63 bit integers. The offset should
-                 * only really be an issue in the year 2262. the tracer in C/ASM
-                 * can write an offset in an unsigned 64 bit long. In java, the
-                 * last bit, being set to 1 will be read as a negative number,
-                 * but since it is too big a positive it will throw an
-                 * exception. this will happen in 2^63 ns from 1970. Therefore
-                 * 293 years from 1970
-                 */
-                Long numValue;
-                try {
-                    numValue = Long.parseLong(text);
-                } catch (NumberFormatException e) {
-                    throw new ParseException("Number conversion issue with " + text, e); //$NON-NLS-1$
-                }
-                ctfClock.addAttribute(key, numValue);
-                break;
-            default:
-                ctfClock.addAttribute(key, text);
-            }
-
-        }
-        String nameValue = ctfClock.getName();
-        fTrace.addClock(nameValue, ctfClock);
     }
 
     private void parseTrace(CommonTree traceNode) throws ParseException {
 
+        CTFTrace trace = fTrace;
         List<CommonTree> children = traceNode.getChildren();
         if (children == null) {
             throw new ParseException("Trace block is empty"); //$NON-NLS-1$
         }
 
-        resetScope();
-
         for (CommonTree child : children) {
             switch (child.getType()) {
             case CTFParser.TYPEALIAS:
-                parseTypealias(child);
+                TypeAliasParser.INSTANCE.parse(child, new TypeAliasParser.Param(trace, fRoot));
                 break;
             case CTFParser.TYPEDEF:
-                parseTypedef(child);
+                TypedefParser.INSTANCE.parse(child, new TypedefParser.Param(trace, fRoot));
                 break;
             case CTFParser.CTF_EXPRESSION_TYPE:
             case CTFParser.CTF_EXPRESSION_VAL:
-                parseTraceDeclaration(child);
+                TraceDeclarationParser.INSTANCE.parse(child, new TraceDeclarationParser.Param(fTrace, fRoot));
                 break;
             default:
                 throw childTypeError(child);
@@ -342,512 +248,6 @@ public class IOStructGen {
         }
     }
 
-    private void parseTraceDeclaration(CommonTree traceDecl)
-            throws ParseException {
-
-        /* There should be a left and right */
-
-        CommonTree leftNode = (CommonTree) traceDecl.getChild(0);
-        CommonTree rightNode = (CommonTree) traceDecl.getChild(1);
-
-        List<CommonTree> leftStrings = leftNode.getChildren();
-
-        if (!isAnyUnaryString(leftStrings.get(0))) {
-            throw new ParseException("Left side of CTF assignment must be a string"); //$NON-NLS-1$
-        }
-
-        String left = concatenateUnaryStrings(leftStrings);
-
-        if (left.equals(MetadataStrings.MAJOR)) {
-            if (fTrace.majorIsSet()) {
-                throw new ParseException("major is already set"); //$NON-NLS-1$
-            }
-
-            fTrace.setMajor(getMajorOrMinor(rightNode));
-        } else if (left.equals(MetadataStrings.MINOR)) {
-            if (fTrace.minorIsSet()) {
-                throw new ParseException("minor is already set"); //$NON-NLS-1$
-            }
-
-            fTrace.setMinor(getMajorOrMinor(rightNode));
-        } else if (left.equals(MetadataStrings.UUID_STRING)) {
-            UUID uuid = getUUID(rightNode);
-
-            /*
-             * If uuid was already set by a metadata packet, compare it to see
-             * if it matches
-             */
-            if (fTrace.uuidIsSet()) {
-                if (fTrace.getUUID().compareTo(uuid) != 0) {
-                    throw new ParseException("UUID mismatch. Packet says " //$NON-NLS-1$
-                            + fTrace.getUUID() + " but metadata says " + uuid); //$NON-NLS-1$
-                }
-            } else {
-                fTrace.setUUID(uuid);
-            }
-
-        } else if (left.equals(MetadataStrings.BYTE_ORDER)) {
-            ByteOrder byteOrder = getByteOrder(rightNode);
-
-            /*
-             * If byte order was already set by a metadata packet, compare it to
-             * see if it matches
-             */
-            if (fTrace.getByteOrder() != null) {
-                if (fTrace.getByteOrder() != byteOrder) {
-                    throw new ParseException(
-                            "Endianness mismatch. Magic number says " //$NON-NLS-1$
-                                    + fTrace.getByteOrder()
-                                    + " but metadata says " + byteOrder); //$NON-NLS-1$
-                }
-            } else {
-                fTrace.setByteOrder(byteOrder);
-
-                final DeclarationScope currentScope = getCurrentScope();
-                for (String type : currentScope.getTypeNames()) {
-                    IDeclaration d = currentScope.lookupType(type);
-                    if (d instanceof IntegerDeclaration) {
-                        addByteOrder(byteOrder, currentScope, type, (IntegerDeclaration) d);
-                    } else if (d instanceof FloatDeclaration) {
-                        addByteOrder(byteOrder, currentScope, type, (FloatDeclaration) d);
-                    } else if (d instanceof EnumDeclaration) {
-                        addByteOrder(byteOrder, currentScope, type, (EnumDeclaration) d);
-                    } else if (d instanceof StructDeclaration) {
-                        setAlign(currentScope, (StructDeclaration) d, byteOrder);
-                    }
-                }
-            }
-        } else if (left.equals(MetadataStrings.PACKET_HEADER)) {
-            if (fTrace.packetHeaderIsSet()) {
-                throw new ParseException("packet.header already defined"); //$NON-NLS-1$
-            }
-
-            CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
-
-            if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
-                throw new ParseException("packet.header expects a type specifier"); //$NON-NLS-1$
-            }
-
-            IDeclaration packetHeaderDecl = parseTypeSpecifierList(typeSpecifier);
-
-            if (!(packetHeaderDecl instanceof StructDeclaration)) {
-                throw new ParseException("packet.header expects a struct"); //$NON-NLS-1$
-            }
-
-            fTrace.setPacketHeader((StructDeclaration) packetHeaderDecl);
-        } else {
-            Activator.log(IStatus.WARNING, Messages.IOStructGen_UnknownTraceAttributeWarning + " " + left); //$NON-NLS-1$
-        }
-    }
-
-    private static void addByteOrder(ByteOrder byteOrder,
-            final DeclarationScope parentScope, String name,
-            IntegerDeclaration decl) throws ParseException {
-
-        if (!decl.isByteOrderSet()) {
-            IntegerDeclaration newI;
-            newI = IntegerDeclaration.createDeclaration(decl.getLength(), decl.isSigned(),
-                    decl.getBase(), byteOrder, decl.getEncoding(),
-                    decl.getClock(), decl.getAlignment());
-            parentScope.replaceType(name, newI);
-        }
-    }
-
-    private static void addByteOrder(ByteOrder byteOrder, DeclarationScope parentScope, String name, EnumDeclaration decl) throws ParseException {
-        final IntegerDeclaration containerType = decl.getContainerType();
-        if (!decl.isByteOrderSet()) {
-            EnumDeclaration newEnum = new EnumDeclaration(IntegerDeclaration.createDeclaration(containerType.getLength(), containerType.isSigned(),
-                    containerType.getBase(), byteOrder, containerType.getEncoding(),
-                    containerType.getClock(), containerType.getAlignment()));
-            for (Entry<String, Pair> entry : decl.getEnumTable().entrySet()) {
-                newEnum.add(entry.getValue().getFirst(), entry.getValue().getSecond(), entry.getKey());
-            }
-
-            parentScope.replaceType(name, newEnum);
-        }
-    }
-
-    private static void addByteOrder(ByteOrder byteOrder, DeclarationScope parentScope, String name, FloatDeclaration decl) throws ParseException {
-        if (!decl.isByteOrderSet()) {
-            FloatDeclaration newFloat = new FloatDeclaration(decl.getExponent(), decl.getMantissa(), byteOrder, decl.getAlignment());
-            parentScope.replaceType(name, newFloat);
-        }
-    }
-
-    private void setAlign(DeclarationScope parentScope, StructDeclaration sd,
-            ByteOrder byteOrder) throws ParseException {
-
-        for (String s : sd.getFieldsList()) {
-            IDeclaration d = sd.getField(s);
-
-            if (d instanceof StructDeclaration) {
-                setAlign(parentScope, (StructDeclaration) d, byteOrder);
-
-            } else if (d instanceof VariantDeclaration) {
-                setAlign(parentScope, (VariantDeclaration) d, byteOrder);
-            } else if (d instanceof IntegerDeclaration) {
-                IntegerDeclaration decl = (IntegerDeclaration) d;
-                if (decl.getByteOrder() != byteOrder) {
-                    IntegerDeclaration newI;
-                    newI = IntegerDeclaration.createDeclaration(decl.getLength(),
-                            decl.isSigned(), decl.getBase(), byteOrder,
-                            decl.getEncoding(), decl.getClock(),
-                            decl.getAlignment());
-                    sd.getFields().put(s, newI);
-                }
-            }
-        }
-    }
-
-    private void setAlign(DeclarationScope parentScope, VariantDeclaration vd,
-            ByteOrder byteOrder) throws ParseException {
-
-        for (String s : vd.getFields().keySet()) {
-            IDeclaration d = vd.getFields().get(s);
-
-            if (d instanceof StructDeclaration) {
-                setAlign(parentScope, (StructDeclaration) d, byteOrder);
-
-            } else if (d instanceof IntegerDeclaration) {
-                IntegerDeclaration decl = (IntegerDeclaration) d;
-                IntegerDeclaration newI;
-                newI = IntegerDeclaration.createDeclaration(decl.getLength(),
-                        decl.isSigned(), decl.getBase(), byteOrder,
-                        decl.getEncoding(), decl.getClock(),
-                        decl.getAlignment());
-                vd.getFields().put(s, newI);
-            }
-        }
-    }
-
-    private void parseStream(CommonTree streamNode) throws ParseException {
-
-        CTFStream stream = new CTFStream(fTrace);
-
-        List<CommonTree> children = streamNode.getChildren();
-        if (children == null) {
-            throw new ParseException("Empty stream block"); //$NON-NLS-1$
-        }
-
-        pushScope(MetadataStrings.STREAM);
-
-        for (CommonTree child : children) {
-            switch (child.getType()) {
-            case CTFParser.TYPEALIAS:
-                parseTypealias(child);
-                break;
-            case CTFParser.TYPEDEF:
-                parseTypedef(child);
-                break;
-            case CTFParser.CTF_EXPRESSION_TYPE:
-            case CTFParser.CTF_EXPRESSION_VAL:
-                parseStreamDeclaration(child, stream);
-                break;
-            default:
-                throw childTypeError(child);
-            }
-        }
-
-        if (stream.isIdSet() &&
-                (!fTrace.packetHeaderIsSet() || !fTrace.getPacketHeader().hasField(MetadataStrings.STREAM_ID))) {
-            throw new ParseException("Stream has an ID, but there is no stream_id field in packet header."); //$NON-NLS-1$
-        }
-
-        fTrace.addStream(stream);
-
-        popScope();
-    }
-
-    private void parseStreamDeclaration(CommonTree streamDecl, CTFStream stream)
-            throws ParseException {
-
-        /* There should be a left and right */
-
-        CommonTree leftNode = (CommonTree) streamDecl.getChild(0);
-        CommonTree rightNode = (CommonTree) streamDecl.getChild(1);
-
-        List<CommonTree> leftStrings = leftNode.getChildren();
-
-        if (!isAnyUnaryString(leftStrings.get(0))) {
-            throw new ParseException("Left side of CTF assignment must be a string"); //$NON-NLS-1$
-        }
-
-        String left = concatenateUnaryStrings(leftStrings);
-
-        if (left.equals(MetadataStrings.ID)) {
-            if (stream.isIdSet()) {
-                throw new ParseException("stream id already defined"); //$NON-NLS-1$
-            }
-
-            long streamID = getStreamID(rightNode);
-
-            stream.setId(streamID);
-        } else if (left.equals(MetadataStrings.EVENT_HEADER)) {
-            if (stream.isEventHeaderSet()) {
-                throw new ParseException("event.header already defined"); //$NON-NLS-1$
-            }
-
-            CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
-
-            if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
-                throw new ParseException("event.header expects a type specifier"); //$NON-NLS-1$
-            }
-
-            IDeclaration eventHeaderDecl = parseTypeSpecifierList(typeSpecifier);
-            DeclarationScope scope = getCurrentScope();
-            DeclarationScope eventHeaderScope = lookupStructName(typeSpecifier, scope);
-            if (eventHeaderScope == null) {
-                throw new ParseException("event.header scope not found"); //$NON-NLS-1$
-            }
-            pushScope(MetadataStrings.EVENT);
-            getCurrentScope().addChild(eventHeaderScope);
-            eventHeaderScope.setName(CTFStrings.HEADER);
-            popScope();
-            if (eventHeaderDecl instanceof StructDeclaration) {
-                stream.setEventHeader((StructDeclaration) eventHeaderDecl);
-            } else if (eventHeaderDecl instanceof IEventHeaderDeclaration) {
-                stream.setEventHeader((IEventHeaderDeclaration) eventHeaderDecl);
-            } else {
-                throw new ParseException("event.header expects a struct"); //$NON-NLS-1$
-            }
-
-        } else if (left.equals(MetadataStrings.EVENT_CONTEXT)) {
-            if (stream.isEventContextSet()) {
-                throw new ParseException("event.context already defined"); //$NON-NLS-1$
-            }
-
-            CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
-
-            if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
-                throw new ParseException("event.context expects a type specifier"); //$NON-NLS-1$
-            }
-
-            IDeclaration eventContextDecl = parseTypeSpecifierList(typeSpecifier);
-
-            if (!(eventContextDecl instanceof StructDeclaration)) {
-                throw new ParseException("event.context expects a struct"); //$NON-NLS-1$
-            }
-
-            stream.setEventContext((StructDeclaration) eventContextDecl);
-        } else if (left.equals(MetadataStrings.PACKET_CONTEXT)) {
-            if (stream.isPacketContextSet()) {
-                throw new ParseException("packet.context already defined"); //$NON-NLS-1$
-            }
-
-            CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
-
-            if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
-                throw new ParseException("packet.context expects a type specifier"); //$NON-NLS-1$
-            }
-
-            IDeclaration packetContextDecl = parseTypeSpecifierList(typeSpecifier);
-
-            if (!(packetContextDecl instanceof StructDeclaration)) {
-                throw new ParseException("packet.context expects a struct"); //$NON-NLS-1$
-            }
-
-            stream.setPacketContext((StructDeclaration) packetContextDecl);
-        } else {
-            Activator.log(IStatus.WARNING, Messages.IOStructGen_UnknownStreamAttributeWarning + " " + left); //$NON-NLS-1$
-        }
-    }
-
-    private static DeclarationScope lookupStructName(CommonTree typeSpecifier, DeclarationScope scope) {
-        /*
-         * This needs a struct.struct_name.name to work, luckily, that is 99.99%
-         * of traces we receive.
-         */
-        final Tree potentialStruct = typeSpecifier.getChild(0);
-        DeclarationScope eventHeaderScope = null;
-        if (potentialStruct.getType() == (CTFParser.STRUCT)) {
-            final Tree potentialStructName = potentialStruct.getChild(0);
-            if (potentialStructName.getType() == (CTFParser.STRUCT_NAME)) {
-                final String name = potentialStructName.getChild(0).getText();
-                eventHeaderScope = scope.lookupChildRecursive(name);
-            }
-        }
-        /*
-         * If that fails, maybe the struct is anonymous
-         */
-        if (eventHeaderScope == null) {
-            eventHeaderScope = scope.lookupChildRecursive(MetadataStrings.STRUCT);
-        }
-        /*
-         * This can still be null
-         */
-        return eventHeaderScope;
-    }
-
-    private void parseEvent(CommonTree eventNode) throws ParseException {
-
-        List<CommonTree> children = eventNode.getChildren();
-        if (children == null) {
-            throw new ParseException("Empty event block"); //$NON-NLS-1$
-        }
-
-        EventDeclaration event = new EventDeclaration();
-
-        pushScope(MetadataStrings.EVENT);
-
-        for (CommonTree child : children) {
-            switch (child.getType()) {
-            case CTFParser.TYPEALIAS:
-                parseTypealias(child);
-                break;
-            case CTFParser.TYPEDEF:
-                parseTypedef(child);
-                break;
-            case CTFParser.CTF_EXPRESSION_TYPE:
-            case CTFParser.CTF_EXPRESSION_VAL:
-                parseEventDeclaration(child, event);
-                break;
-            default:
-                throw childTypeError(child);
-            }
-        }
-
-        if (!event.nameIsSet()) {
-            throw new ParseException("Event name not set"); //$NON-NLS-1$
-        }
-
-        /*
-         * If the event did not specify a stream, then the trace must be single
-         * stream
-         */
-        if (!event.streamIsSet()) {
-            if (fTrace.nbStreams() > 1) {
-                throw new ParseException("Event without stream_id with more than one stream"); //$NON-NLS-1$
-            }
-
-            /*
-             * If the event did not specify a stream, the only existing stream
-             * must not have an id. Note: That behavior could be changed, it
-             * could be possible to just get the only existing stream, whatever
-             * is its id.
-             */
-            ICTFStream iStream = fTrace.getStream(null);
-            if (iStream instanceof CTFStream) {
-
-                CTFStream ctfStream = (CTFStream) iStream;
-                event.setStream(ctfStream);
-            } else {
-                throw new ParseException("Event without stream_id, but there is no stream without id"); //$NON-NLS-1$
-            }
-        }
-
-        /*
-         * Add the event to the stream.
-         */
-        event.getStream().addEvent(event);
-
-        popScope();
-
-    }
-
-    private void parseEventDeclaration(CommonTree eventDecl,
-            EventDeclaration event) throws ParseException {
-
-        /* There should be a left and right */
-
-        CommonTree leftNode = (CommonTree) eventDecl.getChild(0);
-        CommonTree rightNode = (CommonTree) eventDecl.getChild(1);
-
-        List<CommonTree> leftStrings = leftNode.getChildren();
-
-        if (!isAnyUnaryString(leftStrings.get(0))) {
-            throw new ParseException("Left side of CTF assignment must be a string"); //$NON-NLS-1$
-        }
-
-        String left = concatenateUnaryStrings(leftStrings);
-
-        if (left.equals(MetadataStrings.NAME2)) {
-            if (event.nameIsSet()) {
-                throw new ParseException("name already defined"); //$NON-NLS-1$
-            }
-
-            String name = getEventName(rightNode);
-
-            event.setName(name);
-        } else if (left.equals(MetadataStrings.ID)) {
-            if (event.idIsSet()) {
-                throw new ParseException("id already defined"); //$NON-NLS-1$
-            }
-
-            long id = getEventID(rightNode);
-            if (id > Integer.MAX_VALUE) {
-                throw new ParseException("id is greater than int.maxvalue, unsupported. id : " + id); //$NON-NLS-1$
-            }
-            if (id < 0) {
-                throw new ParseException("negative id, unsupported. id : " + id); //$NON-NLS-1$
-            }
-            event.setId((int) id);
-        } else if (left.equals(MetadataStrings.STREAM_ID)) {
-            if (event.streamIsSet()) {
-                throw new ParseException("stream id already defined"); //$NON-NLS-1$
-            }
-
-            long streamId = getStreamID(rightNode);
-
-            ICTFStream iStream = fTrace.getStream(streamId);
-
-            if (iStream instanceof CTFStream) {
-                CTFStream stream = (CTFStream) iStream;
-                event.setStream(stream);
-            } else {
-                throw new ParseException("Stream " + streamId + " not found"); //$NON-NLS-1$ //$NON-NLS-2$
-            }
-
-        } else if (left.equals(MetadataStrings.CONTEXT)) {
-            if (event.contextIsSet()) {
-                throw new ParseException("context already defined"); //$NON-NLS-1$
-            }
-
-            CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
-
-            if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
-                throw new ParseException("context expects a type specifier"); //$NON-NLS-1$
-            }
-
-            IDeclaration contextDecl = parseTypeSpecifierList(typeSpecifier);
-
-            if (!(contextDecl instanceof StructDeclaration)) {
-                throw new ParseException("context expects a struct"); //$NON-NLS-1$
-            }
-
-            event.setContext((StructDeclaration) contextDecl);
-        } else if (left.equals(MetadataStrings.FIELDS_STRING)) {
-            if (event.fieldsIsSet()) {
-                throw new ParseException("fields already defined"); //$NON-NLS-1$
-            }
-
-            CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
-
-            if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
-                throw new ParseException("fields expects a type specifier"); //$NON-NLS-1$
-            }
-
-            IDeclaration fieldsDecl;
-            fieldsDecl = parseTypeSpecifierList(typeSpecifier);
-
-            if (!(fieldsDecl instanceof StructDeclaration)) {
-                throw new ParseException("fields expects a struct"); //$NON-NLS-1$
-            }
-            /*
-             * The underscores in the event names. These underscores were added
-             * by the LTTng tracer.
-             */
-            final StructDeclaration fields = (StructDeclaration) fieldsDecl;
-            event.setFields(fields);
-        } else if (left.equals(MetadataStrings.LOGLEVEL2)) {
-            long logLevel = parseUnaryInteger((CommonTree) rightNode.getChild(0));
-            event.setLogLevel(logLevel);
-        } else {
-            /* Custom event attribute, we'll add it to the attributes map */
-            String right = parseUnaryString((CommonTree) rightNode.getChild(0));
-            event.setCustomAttribute(left, right);
-        }
-    }
-
     /**
      * Parses a declaration at the root level.
      *
@@ -863,13 +263,13 @@ public class IOStructGen {
         for (CommonTree child : children) {
             switch (child.getType()) {
             case CTFParser.TYPEDEF:
-                parseTypedef(child);
+                TypedefParser.INSTANCE.parse(child, new TypedefParser.Param(fTrace, fRoot));
                 break;
             case CTFParser.TYPEALIAS:
-                parseTypealias(child);
+                TypeAliasParser.INSTANCE.parse(child, new TypeAliasParser.Param(fTrace, fRoot));
                 break;
             case CTFParser.TYPE_SPECIFIER_LIST:
-                parseTypeSpecifierList(child);
+                TypeSpecifierListParser.INSTANCE.parse(child, new TypeSpecifierListParser.Param(fTrace, null, null, fRoot));
                 break;
             default:
                 throw childTypeError(child);
@@ -878,2042 +278,21 @@ public class IOStructGen {
     }
 
     /**
-     * Parses a typealias node. It parses the target, the alias, and registers
-     * the type in the current scope.
+     * Throws a ParseException stating that the parent-child relation between
+     * the given node and its parent is not valid. It means that the shape of
+     * the AST is unexpected.
      *
-     * @param typealias
-     *            A TYPEALIAS node.
-     * @throws ParseException
+     * @param child
+     *            The invalid child node.
+     * @return ParseException with details
      */
-    private void parseTypealias(CommonTree typealias) throws ParseException {
-
-        List<CommonTree> children = typealias.getChildren();
-
-        CommonTree target = null;
-        CommonTree alias = null;
-
-        for (CommonTree child : children) {
-            switch (child.getType()) {
-            case CTFParser.TYPEALIAS_TARGET:
-                target = child;
-                break;
-            case CTFParser.TYPEALIAS_ALIAS:
-                alias = child;
-                break;
-            default:
-                throw childTypeError(child);
-            }
-        }
-
-        IDeclaration targetDeclaration = parseTypealiasTarget(target);
-
-        if ((targetDeclaration instanceof VariantDeclaration)
-                && ((VariantDeclaration) targetDeclaration).isTagged()) {
-            throw new ParseException("Typealias of untagged variant is not permitted"); //$NON-NLS-1$
-        }
-
-        String aliasString = parseTypealiasAlias(alias);
-
-        getCurrentScope().registerType(aliasString, targetDeclaration);
-    }
-
-    /**
-     * Parses the target part of a typealias and gets the corresponding
-     * declaration.
-     *
-     * @param target
-     *            A TYPEALIAS_TARGET node.
-     * @return The corresponding declaration.
-     * @throws ParseException
-     */
-    private IDeclaration parseTypealiasTarget(CommonTree target)
-            throws ParseException {
-
-        List<CommonTree> children = target.getChildren();
-
-        CommonTree typeSpecifierList = null;
-        CommonTree typeDeclaratorList = null;
-        CommonTree typeDeclarator = null;
-        StringBuilder identifierSB = new StringBuilder();
-
-        for (CommonTree child : children) {
-            switch (child.getType()) {
-            case CTFParser.TYPE_SPECIFIER_LIST:
-                typeSpecifierList = child;
-                break;
-            case CTFParser.TYPE_DECLARATOR_LIST:
-                typeDeclaratorList = child;
-                break;
-            default:
-                throw childTypeError(child);
-            }
-        }
-
-        if (typeDeclaratorList != null) {
-            /*
-             * Only allow one declarator
-             *
-             * eg: "typealias uint8_t *, ** := puint8_t;" is not permitted,
-             * otherwise the new type puint8_t would maps to two different
-             * types.
-             */
-            if (typeDeclaratorList.getChildCount() != 1) {
-                throw new ParseException("Only one type declarator is allowed in the typealias target"); //$NON-NLS-1$
-            }
-
-            typeDeclarator = (CommonTree) typeDeclaratorList.getChild(0);
-        }
-
-        /* Parse the target type and get the declaration */
-        IDeclaration targetDeclaration = parseTypeDeclarator(typeDeclarator,
-                typeSpecifierList, identifierSB);
-
-        /*
-         * We don't allow identifier in the target
-         *
-         * eg: "typealias uint8_t* hello := puint8_t;", the "hello" is not
-         * permitted
-         */
-        if (identifierSB.length() > 0) {
-            throw new ParseException("Identifier (" + identifierSB.toString() //$NON-NLS-1$
-                    + ") not expected in the typealias target"); //$NON-NLS-1$
-        }
-
-        return targetDeclaration;
-    }
-
-    /**
-     * Parses the alias part of a typealias. It parses the underlying specifier
-     * list and declarator and creates the string representation that will be
-     * used to register the type.
-     *
-     * @param alias
-     *            A TYPEALIAS_ALIAS node.
-     * @return The string representation of the alias.
-     * @throws ParseException
-     */
-    private static String parseTypealiasAlias(CommonTree alias)
-            throws ParseException {
-
-        List<CommonTree> children = alias.getChildren();
-
-        CommonTree typeSpecifierList = null;
-        CommonTree typeDeclaratorList = null;
-        CommonTree typeDeclarator = null;
-        List<CommonTree> pointers = new LinkedList<>();
-
-        for (CommonTree child : children) {
-            switch (child.getType()) {
-            case CTFParser.TYPE_SPECIFIER_LIST:
-                typeSpecifierList = child;
-                break;
-            case CTFParser.TYPE_DECLARATOR_LIST:
-                typeDeclaratorList = child;
-                break;
-            default:
-                throw childTypeError(child);
-            }
-        }
-
-        /* If there is a type declarator list, extract the pointers */
-        if (typeDeclaratorList != null) {
-            /*
-             * Only allow one declarator
-             *
-             * eg: "typealias uint8_t := puint8_t *, **;" is not permitted.
-             */
-            if (typeDeclaratorList.getChildCount() != 1) {
-                throw new ParseException("Only one type declarator is allowed in the typealias alias"); //$NON-NLS-1$
-            }
-
-            typeDeclarator = (CommonTree) typeDeclaratorList.getChild(0);
-
-            List<CommonTree> typeDeclaratorChildren = typeDeclarator.getChildren();
-
-            for (CommonTree child : typeDeclaratorChildren) {
-                switch (child.getType()) {
-                case CTFParser.POINTER:
-                    pointers.add(child);
-                    break;
-                case CTFParser.IDENTIFIER:
-                    throw new ParseException("Identifier (" + child.getText() //$NON-NLS-1$
-                            + ") not expected in the typealias target"); //$NON-NLS-1$
-                default:
-                    throw childTypeError(child);
-                }
-            }
-        }
-
-        return createTypeDeclarationString(typeSpecifierList, pointers);
-    }
-
-    /**
-     * Parses a typedef node. This creates and registers a new declaration for
-     * each declarator found in the typedef.
-     *
-     * @param typedef
-     *            A TYPEDEF node.
-     * @return map of type name to type declaration
-     * @throws ParseException
-     *             If there is an error creating the declaration.
-     */
-    private Map<String, IDeclaration> parseTypedef(CommonTree typedef) throws ParseException {
-
-        CommonTree typeDeclaratorListNode = (CommonTree) typedef.getFirstChildWithType(CTFParser.TYPE_DECLARATOR_LIST);
-
-        CommonTree typeSpecifierListNode = (CommonTree) typedef.getFirstChildWithType(CTFParser.TYPE_SPECIFIER_LIST);
-
-        List<CommonTree> typeDeclaratorList = typeDeclaratorListNode.getChildren();
-
-        Map<String, IDeclaration> declarations = new HashMap<>();
-
-        for (CommonTree typeDeclaratorNode : typeDeclaratorList) {
-            StringBuilder identifierSB = new StringBuilder();
-
-            IDeclaration typeDeclaration = parseTypeDeclarator(
-                    typeDeclaratorNode, typeSpecifierListNode, identifierSB);
-
-            if ((typeDeclaration instanceof VariantDeclaration)
-                    && !((VariantDeclaration) typeDeclaration).isTagged()) {
-                throw new ParseException("Typealias of untagged variant is not permitted"); //$NON-NLS-1$
-            }
-
-            getCurrentScope().registerType(identifierSB.toString(),
-                    typeDeclaration);
-
-            declarations.put(identifierSB.toString(), typeDeclaration);
-        }
-        return declarations;
-    }
-
-    /**
-     * Parses a pair type declarator / type specifier list and returns the
-     * corresponding declaration. If it is present, it also writes the
-     * identifier of the declarator in the given {@link StringBuilder}.
-     *
-     * @param typeDeclarator
-     *            A TYPE_DECLARATOR node.
-     * @param typeSpecifierList
-     *            A TYPE_SPECIFIER_LIST node.
-     * @param identifierSB
-     *            A StringBuilder that will receive the identifier found in the
-     *            declarator.
-     * @return The corresponding declaration.
-     * @throws ParseException
-     *             If there is an error finding or creating the declaration.
-     */
-    private IDeclaration parseTypeDeclarator(CommonTree typeDeclarator,
-            CommonTree typeSpecifierList, StringBuilder identifierSB)
-                    throws ParseException {
-
-        IDeclaration declaration = null;
-        List<CommonTree> children = null;
-        List<CommonTree> pointers = new LinkedList<>();
-        List<CommonTree> lengths = new LinkedList<>();
-        CommonTree identifier = null;
-
-        /* Separate the tokens by type */
-        if (typeDeclarator != null) {
-            children = typeDeclarator.getChildren();
-            for (CommonTree child : children) {
-
-                switch (child.getType()) {
-                case CTFParser.POINTER:
-                    pointers.add(child);
-                    break;
-                case CTFParser.IDENTIFIER:
-                    identifier = child;
-                    break;
-                case CTFParser.LENGTH:
-                    lengths.add(child);
-                    break;
-                default:
-                    throw childTypeError(child);
-                }
-            }
-
-        }
-
-        /*
-         * Parse the type specifier list, which is the "base" type. For example,
-         * it would be int in int a[3][len].
-         */
-        declaration = parseTypeSpecifierList(typeSpecifierList, pointers, identifier);
-
-        /*
-         * Each length subscript means that we must create a nested array or
-         * sequence. For example, int a[3][len] means that we have an array of 3
-         * (sequences of length 'len' of (int)).
-         */
-        if (!lengths.isEmpty()) {
-            /* We begin at the end */
-            Collections.reverse(lengths);
-
-            for (CommonTree length : lengths) {
-                /*
-                 * By looking at the first expression, we can determine whether
-                 * it is an array or a sequence.
-                 */
-                List<CommonTree> lengthChildren = length.getChildren();
-
-                CommonTree first = lengthChildren.get(0);
-                if (isUnaryInteger(first)) {
-                    /* Array */
-                    int arrayLength = (int) parseUnaryInteger(first);
-
-                    if (arrayLength < 1) {
-                        throw new ParseException("Array length is negative"); //$NON-NLS-1$
-                    }
-
-                    /* Create the array declaration. */
-                    declaration = new ArrayDeclaration(arrayLength, declaration);
-                } else if (isAnyUnaryString(first)) {
-                    /* Sequence */
-                    String lengthName = concatenateUnaryStrings(lengthChildren);
-
-                    /* check that lengthName was declared */
-                    if (isSignedIntegerField(lengthName)) {
-                        throw new ParseException("Sequence declared with length that is not an unsigned integer"); //$NON-NLS-1$
-                    }
-                    /* Create the sequence declaration. */
-                    declaration = new SequenceDeclaration(lengthName,
-                            declaration);
-                } else if (isTrace(first)) {
-                    /* Sequence */
-                    String lengthName = parseTraceScope(lengthChildren);
-
-                    /* check that lengthName was declared */
-                    if (isSignedIntegerField(lengthName)) {
-                        throw new ParseException("Sequence declared with length that is not an unsigned integer"); //$NON-NLS-1$
-                    }
-                    /* Create the sequence declaration. */
-                    declaration = new SequenceDeclaration(lengthName,
-                            declaration);
-
-                } else if (isStream(first)) {
-                    /* Sequence */
-                    String lengthName = parseStreamScope(lengthChildren);
-
-                    /* check that lengthName was declared */
-                    if (isSignedIntegerField(lengthName)) {
-                        throw new ParseException("Sequence declared with length that is not an unsigned integer"); //$NON-NLS-1$
-                    }
-                    /* Create the sequence declaration. */
-                    declaration = new SequenceDeclaration(lengthName,
-                            declaration);
-                } else if (isEvent(first)) {
-                    /* Sequence */
-                    String lengthName = parseEventScope(lengthChildren);
-
-                    /* check that lengthName was declared */
-                    if (isSignedIntegerField(lengthName)) {
-                        throw new ParseException("Sequence declared with length that is not an unsigned integer"); //$NON-NLS-1$
-                    }
-                    /* Create the sequence declaration. */
-                    declaration = new SequenceDeclaration(lengthName,
-                            declaration);
-                } else {
-                    throw childTypeError(first);
-                }
-            }
-        }
-
-        if (identifier != null) {
-            final String text = identifier.getText();
-            identifierSB.append(text);
-            registerType(declaration, text);
-        }
-
-        return declaration;
-    }
-
-    private void registerType(IDeclaration declaration, String identifier) throws ParseException {
-        final DeclarationScope currentScope = getCurrentScope();
-        if (declaration instanceof EnumDeclaration) {
-            if (currentScope.lookupEnum(identifier) == null) {
-                currentScope.registerEnum(identifier, (EnumDeclaration) declaration);
-            }
-        } else if (declaration instanceof VariantDeclaration) {
-            currentScope.registerVariant(identifier, (VariantDeclaration) declaration);
-        }
-    }
-
-    private static String parseStreamScope(List<CommonTree> lengthChildren) throws ParseException {
-        List<CommonTree> sublist = lengthChildren.subList(1, lengthChildren.size());
-
-        CommonTree nextElem = (CommonTree) lengthChildren.get(1).getChild(0);
-        String lengthName = null;
-        if (isUnaryString(nextElem)) {
-            lengthName = parseUnaryString(nextElem);
-        }
-
-        int type = nextElem.getType();
-        if ((CTFParser.tokenNames[CTFParser.EVENT]).equals(lengthName)) {
-            type = CTFParser.EVENT;
-        }
-        switch (type) {
-        case CTFParser.IDENTIFIER:
-            lengthName = concatenateUnaryStrings(sublist);
-            break;
-        case CTFParser.EVENT:
-            lengthName = parseEventScope(sublist);
-            break;
-        default:
-            if (lengthName == null) {
-                throw new ParseException("Unsupported scope stream." + nextElem); //$NON-NLS-1$
-            }
-        }
-        return MetadataStrings.STREAM + '.' + lengthName;
-    }
-
-    private static String parseEventScope(List<CommonTree> lengthChildren) throws ParseException {
-        CommonTree nextElem = (CommonTree) lengthChildren.get(1).getChild(0);
-        String lengthName;
-        switch (nextElem.getType()) {
-        case CTFParser.UNARY_EXPRESSION_STRING:
-        case CTFParser.IDENTIFIER:
-            List<CommonTree> sublist = lengthChildren.subList(1, lengthChildren.size());
-            lengthName = MetadataStrings.EVENT + '.' + concatenateUnaryStrings(sublist);
-            break;
-        default:
-            throw new ParseException("Unsupported scope event." + nextElem); //$NON-NLS-1$
-        }
-        return lengthName;
-    }
-
-    private static String parseTraceScope(List<CommonTree> lengthChildren) throws ParseException {
-        CommonTree nextElem = (CommonTree) lengthChildren.get(1).getChild(0);
-        String lengthName;
-        switch (nextElem.getType()) {
-        case CTFParser.IDENTIFIER:
-            lengthName = concatenateUnaryStrings(lengthChildren.subList(1, lengthChildren.size()));
-            break;
-        case CTFParser.STREAM:
-            return parseStreamScope(lengthChildren.subList(1, lengthChildren.size()));
-        default:
-            throw new ParseException("Unsupported scope trace." + nextElem); //$NON-NLS-1$
-        }
-        return lengthName;
-    }
-
-    private static boolean isEvent(CommonTree first) {
-        return first.getType() == CTFParser.EVENT;
-    }
-
-    private static boolean isStream(CommonTree first) {
-        return first.getType() == CTFParser.STREAM;
-    }
-
-    private static boolean isTrace(CommonTree first) {
-        return first.getType() == CTFParser.TRACE;
-    }
-
-    private boolean isSignedIntegerField(String lengthName) throws ParseException {
-        IDeclaration decl = getCurrentScope().lookupIdentifierRecursive(lengthName);
-        if (decl instanceof IntegerDeclaration) {
-            return ((IntegerDeclaration) decl).isSigned();
-        }
-        throw new ParseException("Is not an integer: " + lengthName); //$NON-NLS-1$
-
-    }
-
-    private IDeclaration parseTypeSpecifierList(CommonTree typeSpecifierList) throws ParseException {
-        return parseTypeSpecifierList(typeSpecifierList, null, null);
-    }
-
-    /**
-     * Parses a type specifier list and returns the corresponding declaration.
-     *
-     * @param typeSpecifierList
-     *            A TYPE_SPECIFIER_LIST node.
-     * @param pointerList
-     *            A list of POINTER nodes that apply to the specified type.
-     * @return The corresponding declaration.
-     * @throws ParseException
-     *             If the type has not been defined or if there is an error
-     *             creating the declaration.
-     */
-    private IDeclaration parseTypeSpecifierList(CommonTree typeSpecifierList,
-            List<CommonTree> pointerList, CommonTree identifier) throws ParseException {
-        IDeclaration declaration = null;
-
-        /*
-         * By looking at the first element of the type specifier list, we can
-         * determine which type it belongs to.
-         */
-        CommonTree firstChild = (CommonTree) typeSpecifierList.getChild(0);
-
-        switch (firstChild.getType()) {
-        case CTFParser.FLOATING_POINT:
-            declaration = parseFloat(firstChild);
-            break;
-        case CTFParser.INTEGER:
-            declaration = parseInteger(firstChild);
-            break;
-        case CTFParser.STRING:
-            declaration = parseString(firstChild);
-            break;
-        case CTFParser.STRUCT:
-            declaration = parseStruct(firstChild, identifier);
-            StructDeclaration structDeclaration = (StructDeclaration) declaration;
-            IDeclaration idEnumDecl = structDeclaration.getFields().get("id"); //$NON-NLS-1$
-            if (idEnumDecl instanceof EnumDeclaration) {
-                EnumDeclaration enumDeclaration = (EnumDeclaration) idEnumDecl;
-                ByteOrder bo = enumDeclaration.getContainerType().getByteOrder();
-                if (EventHeaderCompactDeclaration.getEventHeader(bo).isCompactEventHeader(structDeclaration)) {
-                    declaration = EventHeaderCompactDeclaration.getEventHeader(bo);
-                } else if (EventHeaderLargeDeclaration.getEventHeader(bo).isLargeEventHeader(structDeclaration)) {
-                    declaration = EventHeaderLargeDeclaration.getEventHeader(bo);
-                }
-            }
-            break;
-        case CTFParser.VARIANT:
-            declaration = parseVariant(firstChild);
-            break;
-        case CTFParser.ENUM:
-            declaration = parseEnum(firstChild);
-            break;
-        case CTFParser.IDENTIFIER:
-        case CTFParser.FLOATTOK:
-        case CTFParser.INTTOK:
-        case CTFParser.LONGTOK:
-        case CTFParser.SHORTTOK:
-        case CTFParser.SIGNEDTOK:
-        case CTFParser.UNSIGNEDTOK:
-        case CTFParser.CHARTOK:
-        case CTFParser.DOUBLETOK:
-        case CTFParser.VOIDTOK:
-        case CTFParser.BOOLTOK:
-        case CTFParser.COMPLEXTOK:
-        case CTFParser.IMAGINARYTOK:
-            declaration = parseTypeDeclaration(typeSpecifierList, pointerList);
-            break;
-        default:
-            throw childTypeError(firstChild);
-        }
-
-        return declaration;
-    }
-
-    private IDeclaration parseFloat(CommonTree floatingPoint)
-            throws ParseException {
-
-        List<CommonTree> children = floatingPoint.getChildren();
-
-        /*
-         * If the integer has no attributes, then it is missing the size
-         * attribute which is required
-         */
-        if (children == null) {
-            throw new ParseException("float: missing size attribute"); //$NON-NLS-1$
-        }
-
-        /* The return value */
-        FloatDeclaration floatDeclaration = null;
-        ByteOrder byteOrder = fTrace.getByteOrder();
-        long alignment = 0;
-
-        int exponent = DEFAULT_FLOAT_EXPONENT;
-        int mantissa = DEFAULT_FLOAT_MANTISSA;
-
-        /* Iterate on all integer children */
-        for (CommonTree child : children) {
-            switch (child.getType()) {
-            case CTFParser.CTF_EXPRESSION_VAL:
-                /*
-                 * An assignment expression must have 2 children, left and right
-                 */
-
-                CommonTree leftNode = (CommonTree) child.getChild(0);
-                CommonTree rightNode = (CommonTree) child.getChild(1);
-
-                List<CommonTree> leftStrings = leftNode.getChildren();
-
-                if (!isAnyUnaryString(leftStrings.get(0))) {
-                    throw new ParseException("Left side of ctf expression must be a string"); //$NON-NLS-1$
-                }
-                String left = concatenateUnaryStrings(leftStrings);
-
-                if (left.equals(MetadataStrings.EXP_DIG)) {
-                    exponent = (int) parseUnaryInteger((CommonTree) rightNode.getChild(0));
-                } else if (left.equals(MetadataStrings.BYTE_ORDER)) {
-                    byteOrder = getByteOrder(rightNode);
-                } else if (left.equals(MetadataStrings.MANT_DIG)) {
-                    mantissa = (int) parseUnaryInteger((CommonTree) rightNode.getChild(0));
-                } else if (left.equals(MetadataStrings.ALIGN)) {
-                    alignment = getAlignment(rightNode);
-                } else {
-                    throw new ParseException("Float: unknown attribute " + left); //$NON-NLS-1$
-                }
-
-                break;
-            default:
-                throw childTypeError(child);
-            }
-        }
-        int size = mantissa + exponent;
-        if (size == 0) {
-            throw new ParseException("Float missing size attribute"); //$NON-NLS-1$
-        }
-
-        if (alignment == 0) {
-            alignment = DEFAULT_ALIGNMENT;
-        }
-
-        floatDeclaration = new FloatDeclaration(exponent, mantissa, byteOrder, alignment);
-
-        return floatDeclaration;
-
-    }
-
-    /**
-     * Parses a type specifier list as a user-declared type.
-     *
-     * @param typeSpecifierList
-     *            A TYPE_SPECIFIER_LIST node containing a user-declared type.
-     * @param pointerList
-     *            A list of POINTER nodes that apply to the type specified in
-     *            typeSpecifierList.
-     * @return The corresponding declaration.
-     * @throws ParseException
-     *             If the type does not exist (has not been found).
-     */
-    private IDeclaration parseTypeDeclaration(CommonTree typeSpecifierList,
-            List<CommonTree> pointerList) throws ParseException {
-        /* Create the string representation of the type declaration */
-        String typeStringRepresentation = createTypeDeclarationString(
-                typeSpecifierList, pointerList);
-
-        /*
-         * Use the string representation to search the type in the current scope
-         */
-        IDeclaration decl = getCurrentScope().lookupTypeRecursive(
-                typeStringRepresentation);
-
-        if (decl == null) {
-            throw new ParseException("Type " + typeStringRepresentation //$NON-NLS-1$
-                    + " has not been defined."); //$NON-NLS-1$
-        }
-
-        return decl;
-    }
-
-    /**
-     * Parses an integer declaration node.
-     *
-     * @param integer
-     *            An INTEGER node.
-     * @return The corresponding integer declaration.
-     * @throws ParseException
-     */
-    private IntegerDeclaration parseInteger(CommonTree integer)
-            throws ParseException {
-
-        List<CommonTree> children = integer.getChildren();
-
-        /*
-         * If the integer has no attributes, then it is missing the size
-         * attribute which is required
-         */
-        if (children == null) {
-            throw new ParseException("integer: missing size attribute"); //$NON-NLS-1$
-        }
-
-        /* The return value */
-        IntegerDeclaration integerDeclaration = null;
-        boolean signed = false;
-        ByteOrder byteOrder = fTrace.getByteOrder();
-        long size = 0;
-        long alignment = 0;
-        int base = DEFAULT_INT_BASE;
-        @NonNull
-        String clock = EMPTY_STRING;
-
-        Encoding encoding = Encoding.NONE;
-
-        /* Iterate on all integer children */
-        for (CommonTree child : children) {
-            switch (child.getType()) {
-            case CTFParser.CTF_EXPRESSION_VAL:
-                /*
-                 * An assignment expression must have 2 children, left and right
-                 */
-
-                CommonTree leftNode = (CommonTree) child.getChild(0);
-                CommonTree rightNode = (CommonTree) child.getChild(1);
-
-                List<CommonTree> leftStrings = leftNode.getChildren();
-
-                if (!isAnyUnaryString(leftStrings.get(0))) {
-                    throw new ParseException("Left side of ctf expression must be a string"); //$NON-NLS-1$
-                }
-                String left = concatenateUnaryStrings(leftStrings);
-
-                if (left.equals(SIGNED)) {
-                    signed = getSigned(rightNode);
-                } else if (left.equals(MetadataStrings.BYTE_ORDER)) {
-                    byteOrder = getByteOrder(rightNode);
-                } else if (left.equals(SIZE)) {
-                    size = getSize(rightNode);
-                } else if (left.equals(MetadataStrings.ALIGN)) {
-                    alignment = getAlignment(rightNode);
-                } else if (left.equals(BASE)) {
-                    base = getBase(rightNode);
-                } else if (left.equals(ENCODING)) {
-                    encoding = getEncoding(rightNode);
-                } else if (left.equals(MAP)) {
-                    clock = getClock(rightNode);
-                } else {
-                    Activator.log(IStatus.WARNING, Messages.IOStructGen_UnknownIntegerAttributeWarning + " " + left); //$NON-NLS-1$
-                }
-
-                break;
-            default:
-                throw childTypeError(child);
-            }
-        }
-
-        if (size <= 0) {
-            throw new ParseException("Invalid size attribute in Integer: " + size); //$NON-NLS-1$
-        }
-
-        if (alignment == 0) {
-            alignment = DEFAULT_ALIGNMENT;
-        }
-
-        integerDeclaration = IntegerDeclaration.createDeclaration((int) size, signed, base,
-                byteOrder, encoding, clock, alignment);
-
-        return integerDeclaration;
-    }
-
-    @NonNull
-    private static String getClock(CommonTree rightNode) {
-        String clock = rightNode.getChild(1).getChild(0).getChild(0).getText();
-        return clock == null ? EMPTY_STRING : clock;
-    }
-
-    private static StringDeclaration parseString(CommonTree string)
-            throws ParseException {
-
-        List<CommonTree> children = string.getChildren();
-        StringDeclaration stringDeclaration = null;
-
-        if (children == null) {
-            stringDeclaration = StringDeclaration.getStringDeclaration(Encoding.UTF8);
-        } else {
-            Encoding encoding = Encoding.UTF8;
-            for (CommonTree child : children) {
-                switch (child.getType()) {
-                case CTFParser.CTF_EXPRESSION_VAL:
-                    /*
-                     * An assignment expression must have 2 children, left and
-                     * right
-                     */
-
-                    CommonTree leftNode = (CommonTree) child.getChild(0);
-                    CommonTree rightNode = (CommonTree) child.getChild(1);
-
-                    List<CommonTree> leftStrings = leftNode.getChildren();
-
-                    if (!isAnyUnaryString(leftStrings.get(0))) {
-                        throw new ParseException("Left side of ctf expression must be a string"); //$NON-NLS-1$
-                    }
-                    String left = concatenateUnaryStrings(leftStrings);
-
-                    if (left.equals(ENCODING)) {
-                        encoding = getEncoding(rightNode);
-                    } else {
-                        throw new ParseException("String: unknown attribute " //$NON-NLS-1$
-                                + left);
-                    }
-
-                    break;
-                default:
-                    throw childTypeError(child);
-                }
-            }
-
-            stringDeclaration = StringDeclaration.getStringDeclaration(encoding);
-        }
-
-        return stringDeclaration;
-    }
-
-    /**
-     * Parses a struct declaration and returns the corresponding declaration.
-     *
-     * @param struct
-     *            An STRUCT node.
-     * @return The corresponding struct declaration.
-     * @throws ParseException
-     */
-    private StructDeclaration parseStruct(CommonTree struct, CommonTree identifier)
-            throws ParseException {
-
-        List<CommonTree> children = struct.getChildren();
-
-        /* The return value */
-        StructDeclaration structDeclaration = null;
-
-        /* Name */
-        String structName = null;
-        boolean hasName = false;
-
-        /* Body */
-        CommonTree structBody = null;
-        boolean hasBody = false;
-
-        /* Align */
-        long structAlign = 0;
-
-        /* Loop on all children and identify what we have to work with. */
-        for (CommonTree child : children) {
-            switch (child.getType()) {
-            case CTFParser.STRUCT_NAME: {
-                hasName = true;
-                CommonTree structNameIdentifier = (CommonTree) child.getChild(0);
-                structName = structNameIdentifier.getText();
-                break;
-            }
-            case CTFParser.STRUCT_BODY: {
-                hasBody = true;
-
-                structBody = child;
-                break;
-            }
-            case CTFParser.ALIGN: {
-                CommonTree structAlignExpression = (CommonTree) child.getChild(0);
-
-                structAlign = getAlignment(structAlignExpression);
-                break;
-            }
-            default:
-                throw childTypeError(child);
-            }
-        }
-
-        if (!hasName && identifier != null) {
-            structName = identifier.getText();
-            hasName = true;
-        }
-
-        /*
-         * If a struct has just a body and no name (just like the song,
-         * "A Struct With No Name" by America (sorry for that...)), it's a
-         * definition of a new type, so we create the type declaration and
-         * return it. We can't add it to the declaration scope since there is no
-         * name, but that's what we want because it won't be possible to use it
-         * again to declare another field.
-         *
-         * If it has just a name, we look it up in the declaration scope and
-         * return the associated declaration. If it is not found in the
-         * declaration scope, it means that a struct with that name has not been
-         * declared, which is an error.
-         *
-         * If it has both, then we create the type declaration and register it
-         * to the current scope.
-         *
-         * If it has none, then what are we doing here ?
-         */
-        if (hasBody) {
-            /*
-             * If struct has a name, check if already defined in the current
-             * scope.
-             */
-            if (hasName && (getCurrentScope().lookupStruct(structName) != null)) {
-                throw new ParseException("struct " + structName //$NON-NLS-1$
-                        + " already defined."); //$NON-NLS-1$
-            }
-            /* Create the declaration */
-            structDeclaration = new StructDeclaration(structAlign);
-
-            /* Parse the body */
-            parseStructBody(structBody, structDeclaration, structName);
-
-            /* If struct has name, add it to the current scope. */
-            if (hasName) {
-                getCurrentScope().registerStruct(structName, structDeclaration);
-            }
-        } else /* !hasBody */ {
-            if (hasName) {
-                /* Name and !body */
-
-                /* Lookup the name in the current scope. */
-                structDeclaration = getCurrentScope().lookupStructRecursive(structName);
-
-                /*
-                 * If not found, it means that a struct with such name has not
-                 * been defined
-                 */
-                if (structDeclaration == null) {
-                    throw new ParseException("struct " + structName //$NON-NLS-1$
-                            + " is not defined"); //$NON-NLS-1$
-                }
-            } else {
-                /* !Name and !body */
-
-                /* We can't do anything with that. */
-                throw new ParseException("struct with no name and no body"); //$NON-NLS-1$
-            }
-        }
-        return StructDeclarationFlattener.tryFlattenStruct(structDeclaration);
-    }
-
-    /**
-     * Parses a struct body, adding the fields to specified structure
-     * declaration.
-     *
-     * @param structBody
-     *            A STRUCT_BODY node.
-     * @param structDeclaration
-     *            The struct declaration.
-     * @throws ParseException
-     */
-    private void parseStructBody(CommonTree structBody,
-            StructDeclaration structDeclaration, @Nullable String structName) throws ParseException {
-        List<CommonTree> structDeclarations = structBody.getChildren();
-        if (structDeclarations == null) {
-            structDeclarations = Collections.emptyList();
-        }
-
-        /*
-         * If structDeclaration is null, structBody has no children and the
-         * struct body is empty.
-         */
-        pushNamedScope(structName, MetadataStrings.STRUCT);
-
-        for (CommonTree declarationNode : structDeclarations) {
-            switch (declarationNode.getType()) {
-            case CTFParser.TYPEALIAS:
-                parseTypealias(declarationNode);
-                break;
-            case CTFParser.TYPEDEF:
-                parseTypedef(declarationNode);
-                parseStructDeclaration(declarationNode, structDeclaration);
-                break;
-            case CTFParser.SV_DECLARATION:
-                parseStructDeclaration(declarationNode, structDeclaration);
-                break;
-            default:
-                throw childTypeError(declarationNode);
-            }
-        }
-        popScope();
-    }
-
-    /**
-     * Parses a declaration found in a struct.
-     *
-     * @param declaration
-     *            A SV_DECLARATION node.
-     * @param struct
-     *            A struct declaration. (I know, little name clash here...)
-     * @throws ParseException
-     */
-    private void parseStructDeclaration(CommonTree declaration,
-            StructDeclaration struct) throws ParseException {
-
-        /* Get the type specifier list node */
-        CommonTree typeSpecifierListNode = (CommonTree) declaration.getFirstChildWithType(CTFParser.TYPE_SPECIFIER_LIST);
-
-        /* Get the type declarator list node */
-        CommonTree typeDeclaratorListNode = (CommonTree) declaration.getFirstChildWithType(CTFParser.TYPE_DECLARATOR_LIST);
-
-        /* Get the type declarator list */
-        List<CommonTree> typeDeclaratorList = typeDeclaratorListNode.getChildren();
-
-        /*
-         * For each type declarator, parse the declaration and add a field to
-         * the struct
-         */
-        for (CommonTree typeDeclaratorNode : typeDeclaratorList) {
-
-            StringBuilder identifierSB = new StringBuilder();
-
-            IDeclaration decl = parseTypeDeclarator(typeDeclaratorNode,
-                    typeSpecifierListNode, identifierSB);
-            String fieldName = identifierSB.toString();
-            getCurrentScope().registerIdentifier(fieldName, decl);
-
-            if (struct.hasField(fieldName)) {
-                throw new ParseException("struct: duplicate field " //$NON-NLS-1$
-                        + fieldName);
-            }
-
-            struct.addField(fieldName, decl);
-
-        }
-    }
-
-    /**
-     * Parses an enum declaration and returns the corresponding declaration.
-     *
-     * @param theEnum
-     *            An ENUM node.
-     * @return The corresponding enum declaration.
-     * @throws ParseException
-     */
-    private EnumDeclaration parseEnum(CommonTree theEnum) throws ParseException {
-
-        List<CommonTree> children = theEnum.getChildren();
-
-        /* The return value */
-        EnumDeclaration enumDeclaration = null;
-
-        /* Name */
-        String enumName = null;
-
-        /* Body */
-        CommonTree enumBody = null;
-
-        /* Container type */
-        IntegerDeclaration containerTypeDeclaration = null;
-
-        /* Loop on all children and identify what we have to work with. */
-        for (CommonTree child : children) {
-            switch (child.getType()) {
-            case CTFParser.ENUM_NAME: {
-                CommonTree enumNameIdentifier = (CommonTree) child.getChild(0);
-                enumName = enumNameIdentifier.getText();
-                break;
-            }
-            case CTFParser.ENUM_BODY: {
-                enumBody = child;
-                break;
-            }
-            case CTFParser.ENUM_CONTAINER_TYPE: {
-                containerTypeDeclaration = parseEnumContainerType(child);
-                break;
-            }
-            default:
-                throw childTypeError(child);
-            }
-        }
-
-        /*
-         * If the container type has not been defined explicitly, we assume it
-         * is "int".
-         */
-        if (containerTypeDeclaration == null) {
-            IDeclaration enumDecl;
-            /*
-             * it could be because the enum was already declared.
-             */
-            if (enumName != null) {
-                getCurrentScope().setName(enumName);
-                enumDecl = getCurrentScope().lookupEnumRecursive(enumName);
-                if (enumDecl != null) {
-                    return (EnumDeclaration) enumDecl;
-                }
-            }
-
-            IDeclaration decl = getCurrentScope().lookupTypeRecursive("int"); //$NON-NLS-1$
-
-            if (decl == null) {
-                throw new ParseException("enum container type implicit and type int not defined"); //$NON-NLS-1$
-            } else if (!(decl instanceof IntegerDeclaration)) {
-                throw new ParseException("enum container type implicit and type int not an integer"); //$NON-NLS-1$
-            }
-
-            containerTypeDeclaration = (IntegerDeclaration) decl;
-        }
-
-        /*
-         * If it has a body, it's a new declaration, otherwise it's a reference
-         * to an existing declaration. Same logic as struct.
-         */
-        if (enumBody != null) {
-            /*
-             * If enum has a name, check if already defined in the current
-             * scope.
-             */
-            if ((enumName != null)
-                    && (getCurrentScope().lookupEnum(enumName) != null)) {
-                throw new ParseException("enum " + enumName //$NON-NLS-1$
-                        + " already defined"); //$NON-NLS-1$
-            }
-
-            /* Create the declaration */
-            enumDeclaration = new EnumDeclaration(containerTypeDeclaration);
-
-            /* Parse the body */
-            parseEnumBody(enumBody, enumDeclaration, enumName);
-
-            /* If the enum has name, add it to the current scope. */
-            if (enumName != null) {
-                getCurrentScope().registerEnum(enumName, enumDeclaration);
-            }
-        } else {
-            if (enumName != null) {
-                /* Name and !body */
-
-                /* Lookup the name in the current scope. */
-                enumDeclaration = getCurrentScope().lookupEnumRecursive(enumName);
-
-                /*
-                 * If not found, it means that an enum with such name has not
-                 * been defined
-                 */
-                if (enumDeclaration == null) {
-                    throw new ParseException("enum " + enumName //$NON-NLS-1$
-                            + " is not defined"); //$NON-NLS-1$
-                }
-            } else {
-                /* !Name and !body */
-                throw new ParseException("enum with no name and no body"); //$NON-NLS-1$
-            }
-        }
-
-        return enumDeclaration;
-
-    }
-
-    /**
-     * Parses an enum body, adding the enumerators to the specified enum
-     * declaration.
-     *
-     * @param enumBody
-     *            An ENUM_BODY node.
-     * @param enumDeclaration
-     *            The enum declaration.
-     * @throws ParseException
-     */
-    private void parseEnumBody(CommonTree enumBody,
-            EnumDeclaration enumDeclaration, @Nullable String enumName) throws ParseException {
-
-        List<CommonTree> enumerators = enumBody.getChildren();
-        /* enum body can't be empty (unlike struct). */
-
-        pushNamedScope(enumName, MetadataStrings.ENUM);
-
-        /*
-         * Start at -1, so that if the first enumrator has no explicit value, it
-         * will choose 0
-         */
-        long lastHigh = -1;
-
-        for (CommonTree enumerator : enumerators) {
-            lastHigh = parseEnumEnumerator(enumerator, enumDeclaration,
-                    lastHigh);
-        }
-
-        popScope();
-
-    }
-
-    /**
-     * Parses an enumerator node and adds an enumerator declaration to an
-     * enumeration declaration.
-     *
-     * The high value of the range of the last enumerator is needed in case the
-     * current enumerator does not specify its value.
-     *
-     * @param enumerator
-     *            An ENUM_ENUMERATOR node.
-     * @param enumDeclaration
-     *            en enumeration declaration to which will be added the
-     *            enumerator.
-     * @param lastHigh
-     *            The high value of the range of the last enumerator
-     * @return The high value of the value range of the current enumerator.
-     * @throws ParseException
-     */
-    private static long parseEnumEnumerator(CommonTree enumerator,
-            EnumDeclaration enumDeclaration, long lastHigh)
-                    throws ParseException {
-
-        List<CommonTree> children = enumerator.getChildren();
-
-        long low = 0, high = 0;
-        boolean valueSpecified = false;
-        String label = null;
-
-        for (CommonTree child : children) {
-            if (isAnyUnaryString(child)) {
-                label = parseUnaryString(child);
-            } else if (child.getType() == CTFParser.ENUM_VALUE) {
-
-                valueSpecified = true;
-
-                low = parseUnaryInteger((CommonTree) child.getChild(0));
-                high = low;
-            } else if (child.getType() == CTFParser.ENUM_VALUE_RANGE) {
-
-                valueSpecified = true;
-
-                low = parseUnaryInteger((CommonTree) child.getChild(0));
-                high = parseUnaryInteger((CommonTree) child.getChild(1));
-            } else {
-                throw childTypeError(child);
-            }
-        }
-
-        if (!valueSpecified) {
-            low = lastHigh + 1;
-            high = low;
-        }
-
-        if (low > high) {
-            throw new ParseException("enum low value greater than high value"); //$NON-NLS-1$
-        }
-
-        if (!enumDeclaration.add(low, high, label)) {
-            throw new ParseException("enum declarator values overlap."); //$NON-NLS-1$
-        }
-
-        if (valueSpecified && (BigInteger.valueOf(low).compareTo(enumDeclaration.getContainerType().getMinValue()) == -1 ||
-                BigInteger.valueOf(high).compareTo(enumDeclaration.getContainerType().getMaxValue()) == 1)) {
-            throw new ParseException("enum value is not in range"); //$NON-NLS-1$
-        }
-
-        return high;
-    }
-
-    /**
-     * Parses an enum container type node and returns the corresponding integer
-     * type.
-     *
-     * @param enumContainerType
-     *            An ENUM_CONTAINER_TYPE node.
-     * @return An integer declaration corresponding to the container type.
-     * @throws ParseException
-     *             If the type does not parse correctly or if it is not an
-     *             integer type.
-     */
-    private IntegerDeclaration parseEnumContainerType(
-            CommonTree enumContainerType) throws ParseException {
-
-        /* Get the child, which should be a type specifier list */
-        CommonTree typeSpecifierList = (CommonTree) enumContainerType.getChild(0);
-
-        /* Parse it and get the corresponding declaration */
-        IDeclaration decl = parseTypeSpecifierList(typeSpecifierList);
-
-        /* If is is an integer, return it, else throw an error */
-        if (decl instanceof IntegerDeclaration) {
-            return (IntegerDeclaration) decl;
-        }
-        throw new ParseException("enum container type must be an integer"); //$NON-NLS-1$
-    }
-
-    private VariantDeclaration parseVariant(CommonTree variant)
-            throws ParseException {
-
-        List<CommonTree> children = variant.getChildren();
-        VariantDeclaration variantDeclaration = null;
-
-        boolean hasName = false;
-        String variantName = null;
-
-        boolean hasBody = false;
-        CommonTree variantBody = null;
-
-        boolean hasTag = false;
-        String variantTag = null;
-
-        for (CommonTree child : children) {
-            switch (child.getType()) {
-            case CTFParser.VARIANT_NAME:
-
-                hasName = true;
-
-                CommonTree variantNameIdentifier = (CommonTree) child.getChild(0);
-
-                variantName = variantNameIdentifier.getText();
-
-                break;
-            case CTFParser.VARIANT_TAG:
-
-                hasTag = true;
-
-                CommonTree variantTagIdentifier = (CommonTree) child.getChild(0);
-
-                variantTag = variantTagIdentifier.getText();
-
-                break;
-            case CTFParser.VARIANT_BODY:
-
-                hasBody = true;
-
-                variantBody = child;
-
-                break;
-            default:
-                throw childTypeError(child);
-            }
-        }
-
-        if (hasBody) {
-            /*
-             * If variant has a name, check if already defined in the current
-             * scope.
-             */
-            if (hasName
-                    && (getCurrentScope().lookupVariant(variantName) != null)) {
-                throw new ParseException("variant " + variantName //$NON-NLS-1$
-                        + " already defined."); //$NON-NLS-1$
-            }
-
-            /* Create the declaration */
-            variantDeclaration = new VariantDeclaration();
-
-            /* Parse the body */
-            parseVariantBody(variantBody, variantDeclaration, variantName);
-
-            /* If variant has name, add it to the current scope. */
-            if (hasName) {
-                getCurrentScope().registerVariant(variantName,
-                        variantDeclaration);
-            }
-        } else /* !hasBody */ {
-            if (hasName) {
-                /* Name and !body */
-
-                /* Lookup the name in the current scope. */
-                variantDeclaration = getCurrentScope().lookupVariantRecursive(
-                        variantName);
-
-                /*
-                 * If not found, it means that a struct with such name has not
-                 * been defined
-                 */
-                if (variantDeclaration == null) {
-                    throw new ParseException("variant " + variantName //$NON-NLS-1$
-                            + " is not defined"); //$NON-NLS-1$
-                }
-            } else {
-                /* !Name and !body */
-
-                /* We can't do anything with that. */
-                throw new ParseException("variant with no name and no body"); //$NON-NLS-1$
-            }
-        }
-
-        if (hasTag) {
-            variantDeclaration.setTag(variantTag);
-
-            IDeclaration decl = getCurrentScope().lookupIdentifierRecursive(variantTag);
-            if (decl == null) {
-                throw new ParseException("Variant tag not found: " + variantTag); //$NON-NLS-1$
-            }
-            if (!(decl instanceof EnumDeclaration)) {
-                throw new ParseException("Variant tag must be an enum: " + variantTag); //$NON-NLS-1$
-            }
-            EnumDeclaration tagDecl = (EnumDeclaration) decl;
-            Set<String> intersection = new HashSet<>(tagDecl.getLabels());
-            intersection.retainAll(variantDeclaration.getFields().keySet());
-            if (intersection.isEmpty()) {
-                throw new ParseException("Variant contains no values of the tag, impossible to use: " + variantName); //$NON-NLS-1$
-            }
-        }
-
-        return variantDeclaration;
-    }
-
-    private void parseVariantBody(CommonTree variantBody,
-            VariantDeclaration variantDeclaration, @Nullable String variantName) throws ParseException {
-
-        List<CommonTree> variantDeclarations = variantBody.getChildren();
-
-        pushNamedScope(variantName, MetadataStrings.VARIANT);
-
-        for (CommonTree declarationNode : variantDeclarations) {
-            switch (declarationNode.getType()) {
-            case CTFParser.TYPEALIAS:
-                parseTypealias(declarationNode);
-                break;
-            case CTFParser.TYPEDEF:
-                Map<String, IDeclaration> decs = parseTypedef(declarationNode);
-                for (Entry<String, IDeclaration> declarationEntry : decs.entrySet()) {
-                    variantDeclaration.addField(declarationEntry.getKey(), declarationEntry.getValue());
-                }
-                break;
-            case CTFParser.SV_DECLARATION:
-                parseVariantDeclaration(declarationNode, variantDeclaration);
-                break;
-            default:
-                throw childTypeError(declarationNode);
-            }
-        }
-
-        popScope();
-    }
-
-    private void parseVariantDeclaration(CommonTree declaration,
-            VariantDeclaration variant) throws ParseException {
-
-        /* Get the type specifier list node */
-        CommonTree typeSpecifierListNode = (CommonTree) declaration.getFirstChildWithType(CTFParser.TYPE_SPECIFIER_LIST);
-
-        /* Get the type declarator list node */
-        CommonTree typeDeclaratorListNode = (CommonTree) declaration.getFirstChildWithType(CTFParser.TYPE_DECLARATOR_LIST);
-
-        /* Get the type declarator list */
-        List<CommonTree> typeDeclaratorList = typeDeclaratorListNode.getChildren();
-
-        /*
-         * For each type declarator, parse the declaration and add a field to
-         * the variant
-         */
-        for (CommonTree typeDeclaratorNode : typeDeclaratorList) {
-
-            StringBuilder identifierSB = new StringBuilder();
-
-            IDeclaration decl = parseTypeDeclarator(typeDeclaratorNode,
-                    typeSpecifierListNode, identifierSB);
-
-            String name = identifierSB.toString();
-
-            if (variant.hasField(name)) {
-                throw new ParseException("variant: duplicate field " //$NON-NLS-1$
-                        + name);
-            }
-
-            getCurrentScope().registerIdentifier(name, decl);
-
-            variant.addField(name, decl);
-        }
-    }
-
-    /**
-     * Creates the string representation of a type declaration (type specifier
-     * list + pointers).
-     *
-     * @param typeSpecifierList
-     *            A TYPE_SPECIFIER_LIST node.
-     * @param pointers
-     *            A list of POINTER nodes.
-     * @return The string representation.
-     * @throws ParseException
-     */
-    private static String createTypeDeclarationString(
-            CommonTree typeSpecifierList, List<CommonTree> pointers)
-                    throws ParseException {
-        StringBuilder sb = new StringBuilder();
-
-        createTypeSpecifierListString(typeSpecifierList, sb);
-        createPointerListString(pointers, sb);
-
-        return sb.toString();
-    }
-
-    /**
-     * Creates the string representation of a list of type specifiers.
-     *
-     * @param typeSpecifierList
-     *            A TYPE_SPECIFIER_LIST node.
-     * @param sb
-     *            A StringBuilder to which will be appended the string.
-     * @throws ParseException
-     */
-    private static void createTypeSpecifierListString(
-            CommonTree typeSpecifierList, StringBuilder sb)
-                    throws ParseException {
-
-        List<CommonTree> children = typeSpecifierList.getChildren();
-
-        boolean firstItem = true;
-
-        for (CommonTree child : children) {
-            if (!firstItem) {
-                sb.append(' ');
-
-            }
-
-            firstItem = false;
-
-            /* Append the string that represents this type specifier. */
-            createTypeSpecifierString(child, sb);
-        }
-    }
-
-    /**
-     * Creates the string representation of a type specifier.
-     *
-     * @param typeSpecifier
-     *            A TYPE_SPECIFIER node.
-     * @param sb
-     *            A StringBuilder to which will be appended the string.
-     * @throws ParseException
-     */
-    private static void createTypeSpecifierString(CommonTree typeSpecifier,
-            StringBuilder sb) throws ParseException {
-        switch (typeSpecifier.getType()) {
-        case CTFParser.FLOATTOK:
-        case CTFParser.INTTOK:
-        case CTFParser.LONGTOK:
-        case CTFParser.SHORTTOK:
-        case CTFParser.SIGNEDTOK:
-        case CTFParser.UNSIGNEDTOK:
-        case CTFParser.CHARTOK:
-        case CTFParser.DOUBLETOK:
-        case CTFParser.VOIDTOK:
-        case CTFParser.BOOLTOK:
-        case CTFParser.COMPLEXTOK:
-        case CTFParser.IMAGINARYTOK:
-        case CTFParser.CONSTTOK:
-        case CTFParser.IDENTIFIER:
-            sb.append(typeSpecifier.getText());
-            break;
-        case CTFParser.STRUCT: {
-            CommonTree structName = (CommonTree) typeSpecifier.getFirstChildWithType(CTFParser.STRUCT_NAME);
-            if (structName == null) {
-                throw new ParseException("nameless struct found in createTypeSpecifierString"); //$NON-NLS-1$
-            }
-
-            CommonTree structNameIdentifier = (CommonTree) structName.getChild(0);
-
-            sb.append(structNameIdentifier.getText());
-            break;
-        }
-        case CTFParser.VARIANT: {
-            CommonTree variantName = (CommonTree) typeSpecifier.getFirstChildWithType(CTFParser.VARIANT_NAME);
-            if (variantName == null) {
-                throw new ParseException("nameless variant found in createTypeSpecifierString"); //$NON-NLS-1$
-            }
-
-            CommonTree variantNameIdentifier = (CommonTree) variantName.getChild(0);
-
-            sb.append(variantNameIdentifier.getText());
-            break;
-        }
-        case CTFParser.ENUM: {
-            CommonTree enumName = (CommonTree) typeSpecifier.getFirstChildWithType(CTFParser.ENUM_NAME);
-            if (enumName == null) {
-                throw new ParseException("nameless enum found in createTypeSpecifierString"); //$NON-NLS-1$
-            }
-
-            CommonTree enumNameIdentifier = (CommonTree) enumName.getChild(0);
-
-            sb.append(enumNameIdentifier.getText());
-            break;
-        }
-        case CTFParser.FLOATING_POINT:
-        case CTFParser.INTEGER:
-        case CTFParser.STRING:
-            throw new ParseException("CTF type found in createTypeSpecifierString"); //$NON-NLS-1$
-        default:
-            throw childTypeError(typeSpecifier);
-        }
-    }
-
-    /**
-     * Creates the string representation of a list of pointers.
-     *
-     * @param pointerList
-     *            A list of pointer nodes. If pointerList is null, this function
-     *            does nothing.
-     * @param sb
-     *            A stringbuilder to which will be appended the string.
-     */
-    private static void createPointerListString(List<CommonTree> pointerList,
-            StringBuilder sb) {
-        if (pointerList == null) {
-            return;
-        }
-
-        for (CommonTree pointer : pointerList) {
-
-            sb.append(" *"); //$NON-NLS-1$
-            if (pointer.getChildCount() > 0) {
-
-                sb.append(" const"); //$NON-NLS-1$
-            }
-        }
-    }
-
-    /**
-     * @param node
-     *            The node to check.
-     * @return True if the given node is an unary string.
-     */
-    private static boolean isUnaryString(CommonTree node) {
-        return ((node.getType() == CTFParser.UNARY_EXPRESSION_STRING));
-    }
-
-    /**
-     * @param node
-     *            The node to check.
-     * @return True if the given node is any type of unary string (no quotes,
-     *         quotes, etc).
-     */
-    private static boolean isAnyUnaryString(CommonTree node) {
-        return ((node.getType() == CTFParser.UNARY_EXPRESSION_STRING) || (node.getType() == CTFParser.UNARY_EXPRESSION_STRING_QUOTES));
-    }
-
-    /**
-     * @param node
-     *            The node to check.
-     * @return True if the given node is an unary integer.
-     */
-    private static boolean isUnaryInteger(CommonTree node) {
-        return ((node.getType() == CTFParser.UNARY_EXPRESSION_DEC) ||
-                (node.getType() == CTFParser.UNARY_EXPRESSION_HEX) || (node.getType() == CTFParser.UNARY_EXPRESSION_OCT));
-    }
-
-    /**
-     * Parses a unary string node and return the string value.
-     *
-     * @param unaryString
-     *            The unary string node to parse (type UNARY_EXPRESSION_STRING
-     *            or UNARY_EXPRESSION_STRING_QUOTES).
-     * @return The string value.
-     */
-    /*
-     * It would be really nice to remove the quotes earlier, such as in the
-     * parser.
-     */
-    private static String parseUnaryString(CommonTree unaryString) {
-
-        CommonTree value = (CommonTree) unaryString.getChild(0);
-        if (value.getType() == CTFParser.UNARY_EXPRESSION_STRING) {
-            value = (CommonTree) value.getChild(0);
-        }
-        String strval = value.getText();
-
-        /* Remove quotes */
-        if (unaryString.getType() == CTFParser.UNARY_EXPRESSION_STRING_QUOTES) {
-            strval = strval.substring(1, strval.length() - 1);
-        }
-
-        return strval;
-    }
-
-    /**
-     * Parses an unary integer (dec, hex or oct).
-     *
-     * @param unaryInteger
-     *            An unary integer node.
-     * @return The integer value.
-     * @throws ParseException
-     *             on an invalid integer format ("bob" for example)
-     */
-    private static long parseUnaryInteger(CommonTree unaryInteger) throws ParseException {
-
-        List<CommonTree> children = unaryInteger.getChildren();
-        CommonTree value = children.get(0);
-        String strval = value.getText();
-
-        long intval;
-        try {
-            intval = Long.decode(strval);
-        } catch (NumberFormatException e) {
-            throw new ParseException("Invalid integer format: " + strval, e); //$NON-NLS-1$
-        }
-
-        /* The rest of children are sign */
-        if ((children.size() % 2) == 0) {
-            return -intval;
-        }
-        return intval;
-    }
-
-    private static long getMajorOrMinor(CommonTree rightNode)
-            throws ParseException {
-
-        CommonTree firstChild = (CommonTree) rightNode.getChild(0);
-
-        if (isUnaryInteger(firstChild)) {
-            if (rightNode.getChildCount() > 1) {
-                throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
-            }
-
-            long m = parseUnaryInteger(firstChild);
-
-            if (m < 0) {
-                throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
-            }
-
-            return m;
-        }
-        throw new ParseException("Invalid value for major/minor"); //$NON-NLS-1$
-    }
-
-    private static UUID getUUID(CommonTree rightNode) throws ParseException {
-
-        CommonTree firstChild = (CommonTree) rightNode.getChild(0);
-
-        if (isAnyUnaryString(firstChild)) {
-            if (rightNode.getChildCount() > 1) {
-                throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
-            }
-
-            String uuidstr = parseUnaryString(firstChild);
-
-            try {
-                return UUID.fromString(uuidstr);
-            } catch (IllegalArgumentException e) {
-                throw new ParseException("Invalid format for UUID", e); //$NON-NLS-1$
-            }
-        }
-        throw new ParseException("Invalid value for UUID"); //$NON-NLS-1$
-    }
-
-    /**
-     * Gets the value of a "signed" integer attribute.
-     *
-     * @param rightNode
-     *            A CTF_RIGHT node.
-     * @return The "signed" value as a boolean.
-     * @throws ParseException
-     */
-    private static boolean getSigned(CommonTree rightNode)
-            throws ParseException {
-
-        boolean ret = false;
-        CommonTree firstChild = (CommonTree) rightNode.getChild(0);
-
-        if (isUnaryString(firstChild)) {
-            String strval = concatenateUnaryStrings(rightNode.getChildren());
-
-            if (strval.equals(MetadataStrings.TRUE)
-                    || strval.equals(MetadataStrings.TRUE2)) {
-                ret = true;
-            } else if (strval.equals(MetadataStrings.FALSE)
-                    || strval.equals(MetadataStrings.FALSE2)) {
-                ret = false;
-            } else {
-                throw new ParseException("Invalid boolean value " //$NON-NLS-1$
-                        + firstChild.getChild(0).getText());
-            }
-        } else if (isUnaryInteger(firstChild)) {
-            /* Happens if the value is something like "1234.hello" */
-            if (rightNode.getChildCount() > 1) {
-                throw new ParseException("Invalid boolean value"); //$NON-NLS-1$
-            }
-
-            long intval = parseUnaryInteger(firstChild);
-
-            if (intval == 1) {
-                ret = true;
-            } else if (intval == 0) {
-                ret = false;
-            } else {
-                throw new ParseException("Invalid boolean value " //$NON-NLS-1$
-                        + firstChild.getChild(0).getText());
-            }
-        } else {
-            throw new ParseException();
-        }
-
-        return ret;
-    }
-
-    /**
-     * Gets the value of a "byte_order" integer attribute.
-     *
-     * @param rightNode
-     *            A CTF_RIGHT node.
-     * @return The "byte_order" value.
-     * @throws ParseException
-     */
-    private ByteOrder getByteOrder(CommonTree rightNode) throws ParseException {
-
-        CommonTree firstChild = (CommonTree) rightNode.getChild(0);
-
-        if (isUnaryString(firstChild)) {
-            String strval = concatenateUnaryStrings(rightNode.getChildren());
-
-            if (strval.equals(MetadataStrings.LE)) {
-                return ByteOrder.LITTLE_ENDIAN;
-            } else if (strval.equals(MetadataStrings.BE)
-                    || strval.equals(MetadataStrings.NETWORK)) {
-                return ByteOrder.BIG_ENDIAN;
-            } else if (strval.equals(MetadataStrings.NATIVE)) {
-                return fTrace.getByteOrder();
-            } else {
-                throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
-            }
-        }
-        throw new ParseException("Invalid value for byte order"); //$NON-NLS-1$
-    }
-
-    /**
-     * Determines if the given value is a valid alignment value.
-     *
-     * @param alignment
-     *            The value to check.
-     * @return True if it is valid.
-     */
-    private static boolean isValidAlignment(long alignment) {
-        return !((alignment <= 0) || ((alignment & (alignment - 1)) != 0));
-    }
-
-    /**
-     * Gets the value of a "size" integer attribute.
-     *
-     * @param rightNode
-     *            A CTF_RIGHT node.
-     * @return The "size" value.
-     * @throws ParseException
-     */
-    private static long getSize(CommonTree rightNode) throws ParseException {
-
-        CommonTree firstChild = (CommonTree) rightNode.getChild(0);
-
-        if (isUnaryInteger(firstChild)) {
-            if (rightNode.getChildCount() > 1) {
-                throw new ParseException("Invalid value for size"); //$NON-NLS-1$
-            }
-
-            long size = parseUnaryInteger(firstChild);
-
-            if (size < 1) {
-                throw new ParseException("Invalid value for size"); //$NON-NLS-1$
-            }
-
-            return size;
-        }
-        throw new ParseException("Invalid value for size"); //$NON-NLS-1$
-    }
-
-    /**
-     * Gets the value of a "align" integer or struct attribute.
-     *
-     * @param node
-     *            A CTF_RIGHT node or directly an unary integer.
-     * @return The align value.
-     * @throws ParseException
-     */
-    private static long getAlignment(CommonTree node) throws ParseException {
-
-        /*
-         * If a CTF_RIGHT node was passed, call getAlignment with the first
-         * child
-         */
-        if (node.getType() == CTFParser.CTF_RIGHT) {
-            if (node.getChildCount() > 1) {
-                throw new ParseException("Invalid alignment value"); //$NON-NLS-1$
-            }
-
-            return getAlignment((CommonTree) node.getChild(0));
-        } else if (isUnaryInteger(node)) {
-            long alignment = parseUnaryInteger(node);
-
-            if (!isValidAlignment(alignment)) {
-                throw new ParseException("Invalid value for alignment : " //$NON-NLS-1$
-                        + alignment);
-            }
-
-            return alignment;
-        }
-        throw new ParseException("Invalid value for alignment"); //$NON-NLS-1$
-    }
-
-    /**
-     * Gets the value of a "base" integer attribute.
-     *
-     * @param rightNode
-     *            An CTF_RIGHT node.
-     * @return The "base" value.
-     * @throws ParseException
-     */
-    private static int getBase(CommonTree rightNode) throws ParseException {
-
-        CommonTree firstChild = (CommonTree) rightNode.getChild(0);
-
-        if (isUnaryInteger(firstChild)) {
-            if (rightNode.getChildCount() > 1) {
-                throw new ParseException("invalid base value"); //$NON-NLS-1$
-            }
-
-            long intval = parseUnaryInteger(firstChild);
-            if ((intval == INTEGER_BASE_2) || (intval == INTEGER_BASE_8) || (intval == INTEGER_BASE_10)
-                    || (intval == INTEGER_BASE_16)) {
-                return (int) intval;
-            }
-            throw new ParseException("Invalid value for base"); //$NON-NLS-1$
-        } else if (isUnaryString(firstChild)) {
-            switch (concatenateUnaryStrings(rightNode.getChildren())) {
-            case MetadataStrings.DECIMAL:
-            case MetadataStrings.DEC:
-            case MetadataStrings.DEC_CTE:
-            case MetadataStrings.INT_MOD:
-            case MetadataStrings.UNSIGNED_CTE:
-                return INTEGER_BASE_10;
-            case MetadataStrings.HEXADECIMAL:
-            case MetadataStrings.HEX:
-            case MetadataStrings.X:
-            case MetadataStrings.X2:
-            case MetadataStrings.POINTER:
-                return INTEGER_BASE_16;
-            case MetadataStrings.OCT:
-            case MetadataStrings.OCTAL:
-            case MetadataStrings.OCTAL_CTE:
-                return INTEGER_BASE_8;
-            case MetadataStrings.BIN:
-            case MetadataStrings.BINARY:
-                return INTEGER_BASE_2;
-            default:
-                throw new ParseException("Invalid value for base"); //$NON-NLS-1$
-            }
-        } else {
-            throw new ParseException("invalid value for base"); //$NON-NLS-1$
-        }
-    }
-
-    /**
-     * Gets the value of an "encoding" integer attribute.
-     *
-     * @param rightNode
-     *            A CTF_RIGHT node.
-     * @return The "encoding" value.
-     * @throws ParseException
-     */
-    @NonNull
-    private static Encoding getEncoding(CommonTree rightNode)
-            throws ParseException {
-
-        CommonTree firstChild = (CommonTree) rightNode.getChild(0);
-
-        if (isUnaryString(firstChild)) {
-            String strval = concatenateUnaryStrings(rightNode.getChildren());
-
-            if (strval.equals(MetadataStrings.UTF8)) {
-                return Encoding.UTF8;
-            } else if (strval.equals(MetadataStrings.ASCII)) {
-                return Encoding.ASCII;
-            } else if (strval.equals(MetadataStrings.NONE)) {
-                return Encoding.NONE;
-            } else {
-                throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
-            }
-        }
-        throw new ParseException("Invalid value for encoding"); //$NON-NLS-1$
-    }
-
-    private static long getStreamID(CommonTree rightNode) throws ParseException {
-
-        CommonTree firstChild = (CommonTree) rightNode.getChild(0);
-
-        if (isUnaryInteger(firstChild)) {
-            if (rightNode.getChildCount() > 1) {
-                throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
-            }
-
-            long intval = parseUnaryInteger(firstChild);
-
-            return intval;
-        }
-        throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
-    }
-
-    private static String getEventName(CommonTree rightNode)
-            throws ParseException {
-
-        CommonTree firstChild = (CommonTree) rightNode.getChild(0);
-
-        if (isAnyUnaryString(firstChild)) {
-            String str = concatenateUnaryStrings(rightNode.getChildren());
-
-            return str;
-        }
-        throw new ParseException("invalid value for event name"); //$NON-NLS-1$
-    }
-
-    private static long getEventID(CommonTree rightNode) throws ParseException {
-
-        CommonTree firstChild = (CommonTree) rightNode.getChild(0);
-
-        if (isUnaryInteger(firstChild)) {
-            if (rightNode.getChildCount() > 1) {
-                throw new ParseException("invalid value for event id"); //$NON-NLS-1$
-            }
-
-            long intval = parseUnaryInteger(firstChild);
-            if (intval > Integer.MAX_VALUE) {
-                throw new ParseException("Event id larger than int.maxvalue, something is amiss"); //$NON-NLS-1$
-            }
-            return intval;
-        }
-        throw new ParseException("invalid value for event id"); //$NON-NLS-1$
-    }
-
-    /**
-     * Concatenates a list of unary strings separated by arrows (->) or dots.
-     *
-     * @param strings
-     *            A list, first element being an unary string, subsequent
-     *            elements being ARROW or DOT nodes with unary strings as child.
-     * @return The string representation of the unary string chain.
-     */
-    private static String concatenateUnaryStrings(List<CommonTree> strings) {
-
-        StringBuilder sb = new StringBuilder();
-
-        CommonTree first = strings.get(0);
-        sb.append(parseUnaryString(first));
-
-        boolean isFirst = true;
-
-        for (CommonTree ref : strings) {
-            if (isFirst) {
-                isFirst = false;
-                continue;
-            }
-
-            CommonTree id = (CommonTree) ref.getChild(0);
-
-            if (ref.getType() == CTFParser.ARROW) {
-                sb.append("->"); //$NON-NLS-1$
-            } else { /* DOT */
-                sb.append('.');
-            }
-
-            sb.append(parseUnaryString(id));
-        }
-
-        return sb.toString();
-    }
-
-    /**
-     * Throws a ParseException stating that the parent-child relation between
-     * the given node and its parent is not valid. It means that the shape of
-     * the AST is unexpected.
-     *
-     * @param child
-     *            The invalid child node.
-     * @return ParseException with details
-     */
-    private static ParseException childTypeError(CommonTree child) {
-        CommonTree parent = (CommonTree) child.getParent();
-        String error = "Parent " + CTFParser.tokenNames[parent.getType()] //$NON-NLS-1$
-                + " can't have a child of type " //$NON-NLS-1$
-                + CTFParser.tokenNames[child.getType()] + "."; //$NON-NLS-1$
+    private static ParseException childTypeError(CommonTree child) {
+        CommonTree parent = (CommonTree) child.getParent();
+        String error = "Parent " + CTFParser.tokenNames[parent.getType()] //$NON-NLS-1$
+                + " can't have a child of type " //$NON-NLS-1$
+                + CTFParser.tokenNames[child.getType()] + "."; //$NON-NLS-1$
 
         return new ParseException(error);
     }
 
-    // ------------------------------------------------------------------------
-    // Scope management
-    // ------------------------------------------------------------------------
-
-    /**
-     * Adds a new declaration scope on the top of the scope stack.
-     */
-    private void pushScope(String name) {
-        fScope = new DeclarationScope(getCurrentScope(), name);
-    }
-
-    /**
-     * Removes the top declaration scope from the scope stack.
-     */
-    private void popScope() {
-        fScope = getCurrentScope().getParentScope();
-    }
-
-    private void pushNamedScope(@Nullable String name, String defaultName) {
-        pushScope(name == null ? defaultName : name);
-    }
-
-    /**
-     * Returns the current declaration scope.
-     *
-     * @return The current declaration scope.
-     */
-    private DeclarationScope getCurrentScope() {
-        return fScope;
-    }
-
 }
index 7473266a55b52e81f2949bfc3a8916f8a4698e8a..55c4751a781cd15473d66706b7deb78f91aa8ac0 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2013, 2014 Ericsson
+ * Copyright (c) 2013, 2015 Ericsson
  * 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
index a74e2b6e690795a8c6a50001216e3a806331eb47..d2ad2c0886e363a04e6b81907938969cd54e00c9 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal and others
+ * Copyright (c) 2011, 2015 Ericsson, Ecole Polytechnique de Montreal 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
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/ParseException.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/ParseException.java
new file mode 100644 (file)
index 0000000..c76c418
--- /dev/null
@@ -0,0 +1,63 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2015 Ericsson, Ecole Polytechnique de Montreal 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: Matthew Khouzam - Initial API and implementation
+ * Contributors: Simon Marchi - Initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata;
+
+
+/**
+ * <b><u>ParseException</u></b>
+ */
+public class ParseException extends Exception {
+
+    private static final long serialVersionUID = 7901917601459652080L;
+
+    /**
+     * Empty constructor
+     */
+    public ParseException() {
+        super();
+    }
+
+    /**
+     * Constructor
+     *
+     * @param message to be sent to logs
+     */
+    public ParseException(String message) {
+        super(message);
+    }
+
+    /**
+     * Copy constructor
+     * @param e the exception to throw
+     */
+    public ParseException(Exception e) {
+        super(e);
+    }
+
+    /**
+     * Constructs a new exception with the specified detail message and
+     * cause.  <p>Note that the detail message associated with
+     * {@code cause} is <i>not</i> automatically incorporated in
+     * this exception's detail message.
+     *
+     * @param  message the detail message (which is saved for later retrieval
+     *         by the {@link #getMessage()} method).
+     * @param  cause the cause (which is saved for later retrieval by the
+     *         {@link #getCause()} method).  (A <tt>null</tt> value is
+     *         permitted, and indicates that the cause is nonexistent or
+     *         unknown.)
+     */
+    public ParseException(String message, Exception cause) {
+        super(message, cause);
+    }
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/exceptions/CtfAntlrException.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/exceptions/CtfAntlrException.java
deleted file mode 100644 (file)
index bc0d85d..0000000
+++ /dev/null
@@ -1,134 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2013, 2014 Ericsson
- *
- * 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:
- *   Alexandre Montplaisir - Initial API and implementation
- *   Matthew Khouzam - Addition to have more descriptive errors
- *******************************************************************************/
-
-package org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions;
-
-import java.lang.reflect.Field;
-
-import org.antlr.runtime.MismatchedTokenException;
-import org.antlr.runtime.RecognitionException;
-import org.eclipse.tracecompass.ctf.core.CTFException;
-import org.eclipse.tracecompass.ctf.parser.CTFLexer;
-
-/**
- * CTF Reader exception but dealing with Antlr-specific parsing problems.
- *
- * It is separated from the main {@link CTFException} - and is not part of the
- * API - to isolate the Antlr-specific classes and avoid pushing that dependency
- * to the users of this plugin.
- *
- * @author Matthew Khouzam
- */
-public class CtfAntlrException extends CTFException {
-
-    private static final long serialVersionUID = -7078624493350073777L;
-
-    private final int fErrorLine;
-    private final String fFile;
-    private String fExpectingName = ""; //$NON-NLS-1$
-    private int fExpectedValue = -1;
-    private String fActualName = ""; //$NON-NLS-1$
-    private int fActualValue = -1;
-
-    private final int fCharPositionInLine;
-
-    /**
-     * Re-throw the exception but read its data
-     *
-     * @param e
-     *            the previous recognition exception (Antlr specific)
-     */
-    public CtfAntlrException(MismatchedTokenException e) {
-        super(e);
-        fErrorLine = e.line;
-        fCharPositionInLine = e.charPositionInLine;
-        fFile = "metadata"; //$NON-NLS-1$ // we're in CTF, the only thing using antlr is metadata
-        parseMismatchedException(e);
-    }
-
-    /**
-     * Re-throw the exception but read its data
-     *
-     * @param e
-     *            the previous recognition exception (Antlr specific)
-     */
-    public CtfAntlrException(RecognitionException e) {
-        super(e);
-        fErrorLine = e.line;
-        fCharPositionInLine = e.charPositionInLine;
-        fFile = "metadata"; //$NON-NLS-1$ // we're in CTF, the only thing using antlr is metadata
-    }
-
-    /**
-     * Re-throw the exception but read its data
-     *
-     * @param e
-     *            the previous rewrite exception (Antlr specific)
-     */
-    public CtfAntlrException(Exception e) {
-        super(e);
-        fErrorLine = -1;
-        fCharPositionInLine = -1;
-        fFile = "metadata"; //$NON-NLS-1$ // we're in CTF, the only thing using antlr is metadata
-    }
-
-    private void parseMismatchedException(MismatchedTokenException m) {
-        // Iterate through the tokens that are hidden in the CTFLexer
-        // They are private static final int fields.
-        for (Field f : CTFLexer.class.getDeclaredFields()) {
-            f.setAccessible(true);
-            String name;
-            int value;
-            try {
-                name = f.getName();
-                final boolean isInt = (f.getType().isPrimitive());
-                if (isInt) {
-                    value = ((Integer) f.get(null)).intValue();
-                    if (value == m.expecting) {
-                        this.fExpectingName = name;
-                        this.fExpectedValue = value;
-                    }
-                    if (value == m.c) {
-                        this.fActualName = name;
-                        this.fActualValue = value;
-                    }
-                }
-            } catch (NullPointerException e1) {
-                // Pokemon, gotta catch em all!
-                // actually useful since f may not have a
-                // value
-            } catch (IllegalArgumentException e1) {
-                // Catch these exceptions (reflexion)
-            } catch (IllegalAccessException e1) {
-                // Catch these exceptions (reflexion)
-            }
-            if (!this.fExpectingName.isEmpty() && !this.fActualName.isEmpty()) {
-                return;
-            }
-        }
-    }
-
-    @Override
-    public String getMessage() {
-        final String message = super.getMessage();
-        if (fErrorLine == -1) {
-            return message;
-        }
-        String expected = "" + this.fExpectedValue; //$NON-NLS-1$
-        String actual = "" + this.fActualValue; //$NON-NLS-1$
-        String newMessage = message.replaceAll(expected, this.fExpectingName);
-        newMessage = newMessage.replaceAll(actual, this.fActualName);
-        return newMessage + " at " + fFile + ":" + fErrorLine + ":" + fCharPositionInLine; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
-    }
-
-}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/exceptions/ParseException.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/exceptions/ParseException.java
deleted file mode 100644 (file)
index 28edd02..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2011, 2014 Ericsson, Ecole Polytechnique de Montreal 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: Matthew Khouzam - Initial API and implementation
- * Contributors: Simon Marchi - Initial API and implementation
- *******************************************************************************/
-
-package org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions;
-
-
-/**
- * <b><u>ParseException</u></b>
- */
-public class ParseException extends Exception {
-
-    private static final long serialVersionUID = 7901917601459652080L;
-
-    /**
-     * Empty constructor
-     */
-    public ParseException() {
-        super();
-    }
-
-    /**
-     * Constructor
-     *
-     * @param message to be sent to logs
-     */
-    public ParseException(String message) {
-        super(message);
-    }
-
-    /**
-     * Copy constructor
-     * @param e the exception to throw
-     */
-    public ParseException(Exception e) {
-        super(e);
-    }
-
-    /**
-     * Constructs a new exception with the specified detail message and
-     * cause.  <p>Note that the detail message associated with
-     * {@code cause} is <i>not</i> automatically incorporated in
-     * this exception's detail message.
-     *
-     * @param  message the detail message (which is saved for later retrieval
-     *         by the {@link #getMessage()} method).
-     * @param  cause the cause (which is saved for later retrieval by the
-     *         {@link #getCause()} method).  (A <tt>null</tt> value is
-     *         permitted, and indicates that the cause is nonexistent or
-     *         unknown.)
-     */
-    public ParseException(String message, Exception cause) {
-        super(message, cause);
-    }
-}
index 6037ccb3f83f07b8dbeafac6df8b9a2c92e12961..36e70c80f8972075ba076300f314d0acf2225559 100644 (file)
@@ -1,5 +1,5 @@
 ###############################################################################
-# Copyright (c) 2013, 2014 Ericsson
+# Copyright (c) 2013, 2015 Ericsson
 #
 # All rights reserved. This program and the accompanying materials
 # are made available under the terms of the Eclipse Public License v1.0
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/AlignmentParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/AlignmentParser.java
new file mode 100644 (file)
index 0000000..3e57d11
--- /dev/null
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isUnaryInteger;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ * Alignment parser, we define byte-packed types as aligned on the byte size,
+ * namely 8-bit. We define bit-packed types as following on the next bit, as
+ * defined by the Integers section.
+ *
+ * Each basic type must specify its alignment, in bits. Examples of possible
+ * alignments are: bit-packed (align = 1), byte-packed (align = 8), or
+ * word-aligned (e.g. align = 32 or align = 64). The choice depends on the
+ * architecture preference and compactness vs performance trade-offs of the
+ * implementation. Architectures providing fast unaligned write byte-packed
+ * basic types to save space, aligning each type on byte boundaries (8-bit).
+ * Architectures with slow unaligned writes align types on specific alignment
+ * values. If no specific alignment is declared for a type, it is assumed to be
+ * bit-packed for integers with size not multiple of 8 bits and for gcc
+ * bitfields. All other basic types are byte-packed by default. It is however
+ * recommended to always specify the alignment explicitly. Alignment values must
+ * be power of two. Compound types are aligned as specified in their individual
+ * specification.
+ *
+ * The base offset used for field alignment is the start of the packet
+ * containing the field. For instance, a field aligned on 32-bit needs to be at
+ * an offset multiple of 32-bit from the start of the packet that contains it.
+ *
+ * TSDL metadata attribute representation of a specific alignment:
+ *
+ * @author Matthew Khouzam
+ * @author Efficios (javadoc preamble)
+ *
+ */
+public final class AlignmentParser implements ICommonTreeParser {
+
+    /**
+     * Alignment parser instance
+     */
+    public static final AlignmentParser INSTANCE = new AlignmentParser();
+
+    private static final String INVALID_VALUE_FOR_ALIGNMENT = "Invalid value for alignment"; //$NON-NLS-1$
+
+    private AlignmentParser() {
+    }
+
+    /**
+     * Gets the value of a "align" integer or struct attribute.
+     * @param tree
+     *            A CTF_RIGHT node or directly an unary integer.
+     *
+     * @return The align value.
+     * @throws ParseException
+     *             Invalid alignment value
+     */
+    @Override
+    public Long parse(CommonTree tree, ICommonTreeParserParameter param) throws ParseException {
+        /*
+         * If a CTF_RIGHT node was passed, call getAlignment with the first
+         * child
+         */
+        if (tree.getType() == CTFParser.CTF_RIGHT) {
+            if (tree.getChildCount() > 1) {
+                throw new ParseException(INVALID_VALUE_FOR_ALIGNMENT);
+            }
+
+            return parse((CommonTree) tree.getChild(0), param);
+        } else if (isUnaryInteger(tree)) {
+            long alignment = UnaryIntegerParser.INSTANCE.parse(tree, null);
+
+            if (!isValidAlignment(alignment)) {
+                throw new ParseException(INVALID_VALUE_FOR_ALIGNMENT + " : " //$NON-NLS-1$
+                        + alignment);
+            }
+
+            return alignment;
+        }
+        throw new ParseException(INVALID_VALUE_FOR_ALIGNMENT); // $NON-NLS-1$
+    }
+
+    /**
+     * Determines if the given value is a valid alignment value.
+     *
+     * @param alignment
+     *            The value to check.
+     * @return True if it is valid.
+     */
+    private static boolean isValidAlignment(long alignment) {
+        return !((alignment <= 0) || ((alignment & (alignment - 1)) != 0));
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/ByteOrderParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/ByteOrderParser.java
new file mode 100644 (file)
index 0000000..82c4e83
--- /dev/null
@@ -0,0 +1,116 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.concatenateUnaryStrings;
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isUnaryString;
+
+import java.nio.ByteOrder;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ * By default, byte order of a basic type is the byte order described in the
+ * trace description. It can be overridden by specifying a byte_order attribute
+ * for a basic type. Typical use-case is to specify the network byte order (big
+ * endian: be) to save data captured from the network into the trace without
+ * conversion.
+ *
+ * TSDL metadata representation:
+ *
+ * <pre>
+ * /* network and be are aliases * /
+ * byte_order= /* native OR network OR be OR le * /;
+ * </pre>
+ *
+ * The native keyword selects the byte order described in the trace description.
+ * The network byte order is an alias for big endian.
+ *
+ * Even though the trace description section is not per se a type, for sake of
+ * clarity, it should be noted that native and network byte orders are only
+ * allowed within type declaration. The byte_order specified in the trace
+ * description section only accepts be or le values.
+ *
+ * @author Matthew Khouzam
+ * @author Efficios - Javadoc preamble
+ *
+ */
+public final class ByteOrderParser implements ICommonTreeParser {
+
+    /**
+     * Parameter object with a trace
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    public static final class Param implements ICommonTreeParserParameter {
+        private final CTFTrace fTrace;
+
+        /**
+         * Constructor
+         *
+         * @param trace
+         *            the trace
+         */
+        public Param(CTFTrace trace) {
+            fTrace = trace;
+        }
+    }
+
+    /**
+     * Instance
+     */
+    public static final ByteOrderParser INSTANCE = new ByteOrderParser();
+
+    private static final String INVALID_VALUE_FOR_BYTE_ORDER = "Invalid value for byte order"; //$NON-NLS-1$
+
+    private ByteOrderParser() {
+    }
+
+    /**
+     * Gets the value of a "byte_order" integer attribute.
+     *
+     * @param byteOrderTree
+     *            A CTF_RIGHT node.
+     *
+     * @return The "byte_order" value.
+     * @throws ParseException
+     *             if the value is invalid
+     */
+    @Override
+    public final ByteOrder parse(CommonTree byteOrderTree, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        CTFTrace trace = ((Param) param).fTrace;
+        CommonTree firstChild = (CommonTree) byteOrderTree.getChild(0);
+
+        if (isUnaryString(firstChild)) {
+            String strval = concatenateUnaryStrings(byteOrderTree.getChildren());
+
+            if (strval.equals(MetadataStrings.LE)) {
+                return ByteOrder.LITTLE_ENDIAN;
+            } else if (strval.equals(MetadataStrings.BE)
+                    || strval.equals(MetadataStrings.NETWORK)) {
+                return ByteOrder.BIG_ENDIAN;
+            } else if (strval.equals(MetadataStrings.NATIVE)) {
+                ByteOrder byteOrder = trace.getByteOrder();
+                return (byteOrder == null) ? ByteOrder.nativeOrder() : byteOrder;
+            } else {
+                throw new ParseException(INVALID_VALUE_FOR_BYTE_ORDER);
+            }
+        }
+        throw new ParseException(INVALID_VALUE_FOR_BYTE_ORDER);
+    }
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/ClockParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/ClockParser.java
new file mode 100644 (file)
index 0000000..8b4ff61
--- /dev/null
@@ -0,0 +1,156 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.tracecompass.ctf.core.event.CTFClock;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ * Clock metadata allows to describe the clock topology of the system, as well
+ * as to detail each clock parameter. In absence of clock description, it is
+ * assumed that all fields named timestamp use the same clock source, which
+ * increments once per nanosecond.
+ * <p>
+ * Describing a clock and how it is used by streams is threefold: first, the
+ * clock and clock topology should be described in a clock description block,
+ * e.g.:
+ *
+ * <pre>
+clock {
+    name = cycle_counter_sync;
+    uuid = "62189bee-96dc-11e0-91a8-cfa3d89f3923";
+    description = "Cycle counter synchronized across CPUs";
+    freq = 1000000000;           // frequency, in Hz
+    // precision in seconds is: 1000 * (1/freq)
+    precision = 1000;
+
+     // clock value offset from Epoch is:
+     // offset_s + (offset * (1/freq))
+
+    offset_s = 1326476837;
+    offset = 897235420;
+    absolute = FALSE;
+};
+ * </pre>
+ *
+ * The mandatory name field specifies the name of the clock identifier, which
+ * can later be used as a reference. The optional field uuid is the unique
+ * identifier of the clock. It can be used to correlate different traces that
+ * use the same clock. An optional textual description string can be added with
+ * the description field. The freq field is the initial frequency of the clock,
+ * in Hz. If the freq field is not present, the frequency is assumed to be
+ * 1000000000 (providing clock increment of 1 ns). The optional precision field
+ * details the uncertainty on the clock measurements, in (1/freq) units. The
+ * offset_s and offset fields indicate the offset from POSIX.1 Epoch, 1970-01-01
+ * 00:00:00 +0000 (UTC), to the zero of value of the clock. The offset_s field
+ * is in seconds. The offset field is in (1/freq) units. If any of the offset_s
+ * or offset field is not present, it is assigned the 0 value. The field
+ * absolute is TRUE if the clock is a global reference across different clock
+ * UUID (e.g. NTP time). Otherwise, absolute is FALSE, and the clock can be
+ * considered as synchronized only with other clocks that have the same UUID.
+ * <p>
+ * Secondly, a reference to this clock should be added within an integer type:
+ *
+ * <pre>
+typealias integer {
+    size = 64; align = 1; signed = false;
+    map = clock.cycle_counter_sync.value;
+} := uint64_ccnt_t;
+ * </pre>
+ *
+ * Thirdly, stream declarations can reference the clock they use as a timestamp
+ * source:
+ *
+ * <pre>
+struct packet_context {
+    uint64_ccnt_t ccnt_begin;
+    uint64_ccnt_t ccnt_end;
+    // ...
+};
+
+stream {
+    // ...
+    event.header := struct {
+        uint64_ccnt_t timestamp;
+        // ...
+    };
+    packet.context := struct packet_context;
+};
+ * </pre>
+ *
+ * For a N-bit integer type referring to a clock, if the integer overflows
+ * compared to the N low order bits of the clock prior value found in the same
+ * stream, then it is assumed that one, and only one, overflow occurred. It is
+ * therefore important that events encoding time on a small number of bits
+ * happen frequently enough to detect when more than one N-bit overflow occurs.
+ * <p>
+ * In a packet context, clock field names ending with _begin and _end have a
+ * special meaning: this refers to the timestamps at, respectively, the
+ * beginning and the end of each packet.
+ *
+ * @author Matthew Khouzam - Initial API and implementation
+ * @author Efficios (documentation)
+ *
+ */
+public class ClockParser implements ICommonTreeParser {
+
+    /**
+     * Instance
+     */
+    public static final ClockParser INSTANCE = new ClockParser();
+
+    private ClockParser() {
+    }
+
+    @Override
+    public CTFClock parse(CommonTree clock, ICommonTreeParserParameter unused) throws ParseException {
+        List<CommonTree> children = clock.getChildren();
+        CTFClock ctfClock = new CTFClock();
+        for (CommonTree child : children) {
+            final String key = child.getChild(0).getChild(0).getChild(0).getText();
+            final CommonTree value = (CommonTree) child.getChild(1).getChild(0).getChild(0);
+            final int type = value.getType();
+            final String text = value.getText();
+            switch (type) {
+            case CTFParser.INTEGER:
+            case CTFParser.DECIMAL_LITERAL:
+                /*
+                 * Not a pretty hack, this is to make sure that there is no
+                 * number overflow due to 63 bit integers. The offset should
+                 * only really be an issue in the year 2262. the tracer in C/ASM
+                 * can write an offset in an unsigned 64 bit long. In java, the
+                 * last bit, being set to 1 will be read as a negative number,
+                 * but since it is too big a positive it will throw an
+                 * exception. this will happen in 2^63 ns from 1970. Therefore
+                 * 293 years from 1970
+                 */
+                Long numValue;
+                try {
+                    numValue = Long.parseLong(text);
+                } catch (NumberFormatException e) {
+                    throw new ParseException("Number conversion issue with " + text, e); //$NON-NLS-1$
+                }
+                ctfClock.addAttribute(key, numValue);
+                break;
+            default:
+                ctfClock.addAttribute(key, text);
+            }
+
+        }
+        return ctfClock;
+
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/PointerListStringParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/PointerListStringParser.java
new file mode 100644 (file)
index 0000000..228a721
--- /dev/null
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+
+/**
+ * A parser of pointer lists... like x.y.z
+ *
+ * @author Matthew Khouzam - Initial API and implementation
+ */
+public class PointerListStringParser implements ICommonTreeParser {
+
+    /**
+     * Instance
+     */
+    public static final PointerListStringParser INSTANCE = new PointerListStringParser();
+
+    private PointerListStringParser() {
+    }
+
+    /**
+     * Creates the string representation of a type specifier.
+     *
+     * @param pointers
+     *            A TYPE_SPECIFIER node.
+     * @param param
+     *            unused
+     *
+     * @return A StringBuilder to which will be appended the string.
+     */
+    @Override
+    public StringBuilder parse(CommonTree pointers, ICommonTreeParserParameter param) {
+        StringBuilder sb = new StringBuilder();
+        List<CommonTree> pointerList = pointers.getChildren();
+        if (pointers.getChildCount() == 0) {
+            return sb;
+        }
+
+        for (CommonTree pointer : pointerList) {
+
+            sb.append(" *"); //$NON-NLS-1$
+            if (pointer.getChildCount() > 0) {
+                sb.append(" const"); //$NON-NLS-1$
+            }
+        }
+        return sb;
+    }
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/SizeParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/SizeParser.java
new file mode 100644 (file)
index 0000000..46434f8
--- /dev/null
@@ -0,0 +1,70 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isUnaryInteger;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ * Type size, in bits, for integers and floats is that returned by sizeof() in C
+ * multiplied by CHAR_BIT. We require the size of char and unsigned char types
+ * (CHAR_BIT) to be fixed to 8 bits for cross-endianness compatibility.
+ *
+ * TSDL metadata representation:
+ *
+ * <pre>
+ * size = /* value is in bits * /
+ * </pre>
+ *
+ * @author Matthew Khouzam
+ * @author Efficios - javadoc preamble.
+ */
+public class SizeParser implements ICommonTreeParser {
+    private static final String INVALID_VALUE_FOR_SIZE = "Invalid value for size"; //$NON-NLS-1$
+
+    /**
+     * Instance
+     */
+    public static final SizeParser INSTANCE = new SizeParser();
+
+    private SizeParser() {
+    }
+
+    /**
+     * Gets the value of a "size" integer attribute.
+     *
+     * @param rightNode
+     *            A CTF_RIGHT node.
+     * @param param
+     *            unused
+     * @return The "size" value. Can be 4 bytes.
+     * @throws ParseException
+     *             if the size is not an int or a negative
+     */
+    @Override
+    public Long parse(CommonTree rightNode, ICommonTreeParserParameter param) throws ParseException {
+        CommonTree firstChild = (CommonTree) rightNode.getChild(0);
+        if (isUnaryInteger(firstChild)) {
+            if (rightNode.getChildCount() > 1) {
+                throw new ParseException(INVALID_VALUE_FOR_SIZE);
+            }
+            long size = UnaryIntegerParser.INSTANCE.parse(firstChild, null);
+            if (size < 1) {
+                throw new ParseException(INVALID_VALUE_FOR_SIZE);
+            }
+            return size;
+        }
+        throw new ParseException(INVALID_VALUE_FOR_SIZE);
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TsdlUtils.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TsdlUtils.java
new file mode 100644 (file)
index 0000000..2ad93b2
--- /dev/null
@@ -0,0 +1,125 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ * TSDL utils, this class provides some simple verifications for a common tree.
+ * These are useful before parsing.
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public final class TsdlUtils {
+
+    private static final UnaryStringParser STRING_PARSER = UnaryStringParser.INSTANCE;
+
+    private TsdlUtils() {
+    }
+
+    /**
+     * Is the tree a unary string
+     *
+     * @param node
+     *            The node to check.
+     * @return True if the given node is an unary string.
+     */
+    public static boolean isUnaryString(CommonTree node) {
+        return ((node.getType() == CTFParser.UNARY_EXPRESSION_STRING));
+    }
+
+    /**
+     * Is the tree a unary string or a quoted string
+     *
+     * @param node
+     *            The node to check.
+     * @return True if the given node is any type of unary string (no quotes,
+     *         quotes, etc).
+     */
+    public static boolean isAnyUnaryString(CommonTree node) {
+        return (isUnaryString(node) || (node.getType() == CTFParser.UNARY_EXPRESSION_STRING_QUOTES));
+    }
+
+    /**
+     * Is the tree a unary integer
+     *
+     * @param node
+     *            The node to check.
+     * @return True if the given node is an unary integer.
+     */
+    public static boolean isUnaryInteger(CommonTree node) {
+        return ((node.getType() == CTFParser.UNARY_EXPRESSION_DEC) ||
+                (node.getType() == CTFParser.UNARY_EXPRESSION_HEX) || (node.getType() == CTFParser.UNARY_EXPRESSION_OCT));
+    }
+
+    /**
+     * Concatenates a list of unary strings separated by arrows (->) or dots.
+     *
+     * @param strings
+     *            A list, first element being an unary string, subsequent
+     *            elements being ARROW or DOT nodes with unary strings as child.
+     * @return The string representation of the unary string chain.
+     * @throws ParseException
+     *             If the strings list contains a non-string element
+     */
+    public static @NonNull String concatenateUnaryStrings(List<CommonTree> strings) throws ParseException {
+
+        StringBuilder sb = new StringBuilder();
+
+        CommonTree first = strings.get(0);
+        sb.append(STRING_PARSER.parse(first, null));
+
+        boolean isFirst = true;
+
+        for (CommonTree ref : strings) {
+            if (isFirst) {
+                isFirst = false;
+                continue;
+            }
+
+            CommonTree id = (CommonTree) ref.getChild(0);
+
+            if (ref.getType() == CTFParser.ARROW) {
+                sb.append("->"); //$NON-NLS-1$
+            } else { /* DOT */
+                sb.append('.');
+            }
+
+            sb.append(STRING_PARSER.parse(id, null));
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * Throws a ParseException stating that the parent-child relation between
+     * the given node and its parent is not valid. It means that the shape of
+     * the AST is unexpected.
+     *
+     * @param child
+     *            The invalid child node.
+     * @return ParseException with details
+     */
+    public static ParseException childTypeError(CommonTree child) {
+        CommonTree parent = (CommonTree) child.getParent();
+        String error = "Parent " + CTFParser.tokenNames[parent.getType()] //$NON-NLS-1$
+                + " can't have a child of type " //$NON-NLS-1$
+                + CTFParser.tokenNames[child.getType()] + "."; //$NON-NLS-1$
+
+        return new ParseException(error);
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeAliasAliasParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeAliasAliasParser.java
new file mode 100644 (file)
index 0000000..1a19d7f
--- /dev/null
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.childTypeError;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ * The "typealias" declaration can be used to give a name (including pointer
+ * declarator specifier) to a type. It should also be used to map basic C types
+ * (float, int, unsigned long, ...) to a CTF type. Typealias is a superset of
+ * "typedef": it also allows assignment of a simple variable identifier to a
+ * type.
+ *
+ * @author Matthew Khouzam - Inital API and implementation
+ * @author Efficios - Documentation
+ *
+ */
+public class TypeAliasAliasParser implements ICommonTreeParser {
+
+    /**
+     * Instance
+     */
+    public static final TypeAliasAliasParser INSTANCE = new TypeAliasAliasParser();
+
+    private TypeAliasAliasParser() {
+    }
+
+    /**
+     * Parses the alias part of a typealias. It parses the underlying specifier
+     * list and declarator and creates the string representation that will be
+     * used to register the type. In typealias integer{ blabla } := int, the
+     * alias is the <em>integer{ blabla }</em> part, and the target is the
+     * <em>int</em> part.
+     *
+     * @param typeSpecifier
+     *            A TYPEALIAS_ALIAS node.
+     * @param param
+     *            unused
+     *
+     * @return The string representation of the alias.
+     * @throws ParseException
+     *             if an alias is not allowed here
+     */
+    @Override
+    public String parse(CommonTree typeSpecifier, ICommonTreeParserParameter param) throws ParseException {
+
+        List<CommonTree> children = typeSpecifier.getChildren();
+
+        CommonTree typeSpecifierList = null;
+        CommonTree typeDeclaratorList = null;
+        CommonTree typeDeclarator = null;
+        List<CommonTree> pointers = new LinkedList<>();
+
+        for (CommonTree child : children) {
+            switch (child.getType()) {
+            case CTFParser.TYPE_SPECIFIER_LIST:
+                typeSpecifierList = child;
+                break;
+            case CTFParser.TYPE_DECLARATOR_LIST:
+                typeDeclaratorList = child;
+                break;
+            default:
+                throw childTypeError(child);
+            }
+        }
+
+        /* If there is a type declarator list, extract the pointers */
+        if (typeDeclaratorList != null) {
+            /*
+             * Only allow one declarator
+             *
+             * eg: "typealias uint8_t := puint8_t *, **;" is not permitted.
+             */
+            if (typeDeclaratorList.getChildCount() != 1) {
+                throw new ParseException("Only one type declarator is allowed in the typealias alias"); //$NON-NLS-1$
+            }
+
+            typeDeclarator = (CommonTree) typeDeclaratorList.getChild(0);
+
+            List<CommonTree> typeDeclaratorChildren = typeDeclarator.getChildren();
+
+            for (CommonTree child : typeDeclaratorChildren) {
+                switch (child.getType()) {
+                case CTFParser.POINTER:
+                    pointers.add(child);
+                    break;
+                case CTFParser.IDENTIFIER:
+                    throw new ParseException("Identifier (" + child.getText() //$NON-NLS-1$
+                            + ") not expected in the typealias target"); //$NON-NLS-1$
+                default:
+                    throw childTypeError(child);
+                }
+            }
+        }
+
+        return TypeDeclarationStringParser.INSTANCE.parse(typeSpecifierList, new TypeDeclarationStringParser.Param(pointers));
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeAliasParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeAliasParser.java
new file mode 100644 (file)
index 0000000..959a36d
--- /dev/null
@@ -0,0 +1,109 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.childTypeError;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.VariantDeclaration;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ * The "typealias" declaration can be used to give a name (including pointer
+ * declarator specifier) to a type. It should also be used to map basic C types
+ * (float, int, unsigned long, ...) to a CTF type. Typealias is a superset of
+ * "typedef": it also allows assignment of a simple variable identifier to a
+ * type.
+ *
+ * @author Matthew Khouzam - Inital API and implementation
+ * @author Efficios - Documentation
+ *
+ */
+public class TypeAliasParser extends AbstractScopedCommonTreeParser {
+
+    /**
+     * Parameters for the typealias parser
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+        private final DeclarationScope fDeclarationScope;
+        private final CTFTrace fTrace;
+
+        /**
+         * Parameter constructor
+         *
+         * @param trace
+         *            the trace
+         * @param scope
+         *            the scope
+         */
+        public Param(CTFTrace trace, DeclarationScope scope) {
+            fTrace = trace;
+            fDeclarationScope = scope;
+        }
+    }
+
+    /**
+     * Instance
+     */
+    public final static TypeAliasParser INSTANCE = new TypeAliasParser();
+
+    private TypeAliasParser() {
+    }
+
+    @Override
+    public IDeclaration parse(CommonTree typealias, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        DeclarationScope scope = ((Param) param).fDeclarationScope;
+
+        List<CommonTree> children = typealias.getChildren();
+
+        CommonTree target = null;
+        CommonTree alias = null;
+
+        for (CommonTree child : children) {
+            switch (child.getType()) {
+            case CTFParser.TYPEALIAS_TARGET:
+                target = child;
+                break;
+            case CTFParser.TYPEALIAS_ALIAS:
+                alias = child;
+                break;
+            default:
+                throw childTypeError(child);
+            }
+        }
+        CTFTrace trace = ((Param) param).fTrace;
+        IDeclaration targetDeclaration = TypeAliasTargetParser.INSTANCE.parse(target, new TypeAliasTargetParser.Param(trace, scope));
+
+        if ((targetDeclaration instanceof VariantDeclaration)
+                && ((VariantDeclaration) targetDeclaration).isTagged()) {
+            throw new ParseException("Typealias of untagged variant is not permitted"); //$NON-NLS-1$
+        }
+
+        String aliasString = TypeAliasAliasParser.INSTANCE.parse(alias, null);
+
+        scope.registerType(aliasString, targetDeclaration);
+        return targetDeclaration;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeAliasTargetParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeAliasTargetParser.java
new file mode 100644 (file)
index 0000000..348b94d
--- /dev/null
@@ -0,0 +1,147 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.childTypeError;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ * Type alias targets are the nodes of the declaration of the typealiases.
+ * Typealiases are a superset of typedef defined in TSDL.
+ *
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public class TypeAliasTargetParser extends AbstractScopedCommonTreeParser {
+
+    /**
+     * A parameter object with a trace and a scope
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+        private final DeclarationScope fDeclarationScope;
+        private final CTFTrace fTrace;
+
+        /**
+         * Constructor
+         *
+         * @param trace
+         *            the trace
+         * @param scope
+         *            the current scope
+         */
+        public Param(CTFTrace trace, DeclarationScope scope) {
+            fTrace = trace;
+            fDeclarationScope = scope;
+        }
+    }
+
+    /**
+     * The instance
+     */
+    public final static TypeAliasTargetParser INSTANCE = new TypeAliasTargetParser();
+
+    private TypeAliasTargetParser() {
+    }
+
+    /**
+     * Parses the target part of a typealias and gets the corresponding
+     * declaration. In typealias integer{ blabla } := int, the alias is the
+     * <em>integer{ blabla }</em> part, and the target is the <em>int</em> part.
+     *
+     * Typealiases only allow one declarator.
+     *
+     * eg: "typealias uint8_t *, ** := puint8_t;" is not permitted, otherwise
+     * the new type puint8_t would maps to two different types.
+     *
+     * @param target
+     *            A TYPEALIAS_TARGET node.
+     *
+     * @return The corresponding declaration.
+     * @throws ParseException
+     *             an invalid child in the tree
+     */
+    @Override
+    public IDeclaration parse(CommonTree target, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        DeclarationScope scope = ((Param) param).fDeclarationScope;
+
+        List<CommonTree> children = target.getChildren();
+
+        CommonTree typeSpecifierList = null;
+        CommonTree typeDeclaratorList = null;
+        CommonTree typeDeclarator = null;
+        StringBuilder identifierSB = new StringBuilder();
+
+        for (CommonTree child : children) {
+            switch (child.getType()) {
+            case CTFParser.TYPE_SPECIFIER_LIST:
+                typeSpecifierList = child;
+                break;
+            case CTFParser.TYPE_DECLARATOR_LIST:
+                typeDeclaratorList = child;
+                break;
+            default:
+                throw childTypeError(child);
+            }
+        }
+
+        if (typeDeclaratorList != null) {
+            /*
+             * Only allow one declarator
+             *
+             * eg: "typealias uint8_t *, ** := puint8_t;" is not permitted,
+             * otherwise the new type puint8_t would maps to two different
+             * types.
+             */
+            if (typeDeclaratorList.getChildCount() != 1) {
+                throw new ParseException("Only one type declarator is allowed in the typealias target"); //$NON-NLS-1$
+            }
+
+            typeDeclarator = (CommonTree) typeDeclaratorList.getChild(0);
+        }
+        if (typeSpecifierList == null) {
+            throw new ParseException("Cannot have a typealias with no specifiers"); //$NON-NLS-1$
+        }
+        CTFTrace trace = ((Param) param).fTrace;
+        /* Parse the target type and get the declaration */
+        IDeclaration targetDeclaration = TypeDeclaratorParser.INSTANCE.parse(typeDeclarator,
+                new TypeDeclaratorParser.Param(trace, typeSpecifierList, scope, identifierSB));
+
+        /*
+         * We don't allow identifier in the target
+         *
+         * eg: "typealias uint8_t* hello := puint8_t;", the "hello" is not
+         * permitted
+         */
+        if (identifierSB.length() > 0) {
+            throw new ParseException("Identifier (" + identifierSB.toString() //$NON-NLS-1$
+                    + ") not expected in the typealias target"); //$NON-NLS-1$
+        }
+
+        return targetDeclaration;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeDeclarationParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeDeclarationParser.java
new file mode 100644 (file)
index 0000000..99ae771
--- /dev/null
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ * Basic parser for all abstract data types
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public class TypeDeclarationParser extends AbstractScopedCommonTreeParser {
+
+    /**
+     * Parameter object with a current scope and a list of pointers
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+        private final DeclarationScope fDeclarationScope;
+        private final @Nullable List<CommonTree> fPointerList;
+
+        /**
+         * Constructor
+         *
+         * @param pointerList
+         *            the list of pointers
+         * @param scope
+         *            the current scope
+         */
+        public Param(@Nullable List<CommonTree> pointerList, DeclarationScope scope) {
+            fPointerList = pointerList;
+            fDeclarationScope = scope;
+        }
+    }
+
+    /**
+     * Instance
+     */
+    public final static TypeDeclarationParser INSTANCE = new TypeDeclarationParser();
+
+    private TypeDeclarationParser() {
+    }
+
+    /**
+     * Parses a type specifier list as a user-declared type.
+     *
+     * @param typeSpecifierList
+     *            A TYPE_SPECIFIER_LIST node containing a user-declared type.
+     * @param param
+     *            (pointerList, currentscope) A list of POINTER nodes that apply
+     *            to the type specified in typeSpecifierList.
+     *
+     * @return The corresponding declaration.
+     * @throws ParseException
+     *             If the type does not exist (has not been found).
+     */
+    @Override
+    public IDeclaration parse(CommonTree typeSpecifierList, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        DeclarationScope scope = ((Param) param).fDeclarationScope;
+
+        List<CommonTree> pointerList = ((Param) param).fPointerList;
+        /* Create the string representation of the type declaration */
+        String typeStringRepresentation = TypeDeclarationStringParser.INSTANCE.parse(typeSpecifierList, new TypeDeclarationStringParser.Param(pointerList));
+
+        /*
+         * Use the string representation to search the type in the current scope
+         */
+        IDeclaration decl = scope.lookupTypeRecursive(typeStringRepresentation);
+
+        if (decl == null) {
+            throw new ParseException("Type " + typeStringRepresentation //$NON-NLS-1$
+                    + " has not been defined."); //$NON-NLS-1$
+        }
+
+        return decl;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeDeclarationStringParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeDeclarationStringParser.java
new file mode 100644 (file)
index 0000000..8541559
--- /dev/null
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ * Type declaration String parser
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public class TypeDeclarationStringParser implements ICommonTreeParser {
+
+    /**
+     * Parameter Object with a list of common trees
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    public static final class Param implements ICommonTreeParserParameter {
+        private final List<CommonTree> fList;
+
+        /**
+         * Constructor
+         *
+         * @param list
+         *            List of trees
+         */
+        public Param(List<CommonTree> list) {
+            fList = list;
+        }
+    }
+
+    /**
+     * Instance
+     */
+    public static final TypeDeclarationStringParser INSTANCE = new TypeDeclarationStringParser();
+
+    private TypeDeclarationStringParser() {
+    }
+
+    /**
+     * Creates the string representation of a type specifier.
+     *
+     * @param typeSpecifierList
+     *            A TYPE_SPECIFIER node.
+     *
+     * @return A StringBuilder to which will be appended the string.
+     * @throws ParseException
+     *             invalid node
+     */
+    @Override
+    public String parse(CommonTree typeSpecifierList, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        List<CommonTree> pointers = ((Param) param).fList;
+        StringBuilder sb = new StringBuilder();
+        sb.append(TypeSpecifierListStringParser.INSTANCE.parse(typeSpecifierList, null));
+        if (pointers != null) {
+            CommonTree temp = new CommonTree();
+            for (CommonTree pointer : pointers) {
+                temp.addChild(pointer);
+            }
+            sb.append(PointerListStringParser.INSTANCE.parse(temp, null));
+        }
+        return sb.toString();
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeDeclaratorParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeDeclaratorParser.java
new file mode 100644 (file)
index 0000000..aaecf66
--- /dev/null
@@ -0,0 +1,252 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.childTypeError;
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.concatenateUnaryStrings;
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isAnyUnaryString;
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isUnaryInteger;
+
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.event.EventScopeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.stream.StreamScopeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.trace.TraceScopeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.types.ArrayDeclaration;
+import org.eclipse.tracecompass.internal.ctf.core.event.types.SequenceDeclaration;
+
+/**
+ * A type declarator parser
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public class TypeDeclaratorParser extends AbstractScopedCommonTreeParser {
+
+    /**
+     * The parameter object for type declarator parsers
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+        private final DeclarationScope fDeclarationScope;
+        private final CommonTree fListNode;
+        private final StringBuilder fBuilder;
+        private final CTFTrace fTrace;
+
+        /**
+         * Parameter constructor
+         *
+         * @param trace
+         *            the trace
+         * @param listNode
+         *            the listNode
+         * @param scope
+         *            the scope
+         * @param builder
+         *            the string builder to populate
+         */
+        public Param(CTFTrace trace, CommonTree listNode, DeclarationScope scope, StringBuilder builder) {
+            fTrace = trace;
+            fListNode = listNode;
+            fDeclarationScope = scope;
+            fBuilder = builder;
+        }
+    }
+
+    /**
+     * The instance
+     */
+    public final static TypeDeclaratorParser INSTANCE = new TypeDeclaratorParser();
+
+    private TypeDeclaratorParser() {
+    }
+
+    /**
+     * Parses a pair type declarator / type specifier list and returns the
+     * corresponding declaration. If it is present, it also writes the
+     * identifier of the declarator in the given {@link StringBuilder}.
+     *
+     * @param typeDeclarator
+     *            A TYPE_DECLARATOR node.
+     * @param param
+     *            the parameter object
+     * @return The corresponding declaration.
+     * @throws ParseException
+     *             If there is an error finding or creating the declaration.
+     */
+    @Override
+    public IDeclaration parse(CommonTree typeDeclarator, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        DeclarationScope scope = ((Param) param).fDeclarationScope;
+        CTFTrace trace = ((Param) param).fTrace;
+        CommonTree typeSpecifierList = ((Param) param).fListNode;
+
+        IDeclaration declaration = null;
+        List<CommonTree> children = null;
+        List<@NonNull CommonTree> pointers = new LinkedList<>();
+        List<CommonTree> lengths = new LinkedList<>();
+        CommonTree identifier = null;
+
+        /* Separate the tokens by type */
+        if (typeDeclarator != null) {
+            children = typeDeclarator.getChildren();
+            for (CommonTree child : children) {
+
+                switch (child.getType()) {
+                case CTFParser.POINTER:
+                    pointers.add(child);
+                    break;
+                case CTFParser.IDENTIFIER:
+                    identifier = child;
+                    break;
+                case CTFParser.LENGTH:
+                    lengths.add(child);
+                    break;
+                default:
+                    throw childTypeError(child);
+                }
+            }
+
+        }
+
+        /*
+         * Parse the type specifier list, which is the "base" type. For example,
+         * it would be int in int a[3][len].
+         */
+        declaration = TypeSpecifierListParser.INSTANCE.parse(typeSpecifierList, new TypeSpecifierListParser.Param(trace, pointers, identifier, scope));
+
+        /*
+         * Each length subscript means that we must create a nested array or
+         * sequence. For example, int a[3][len] means that we have an array of 3
+         * (sequences of length 'len' of (int)).
+         */
+        if (!lengths.isEmpty()) {
+            /* We begin at the end */
+            Collections.reverse(lengths);
+
+            for (CommonTree length : lengths) {
+                /*
+                 * By looking at the first expression, we can determine whether
+                 * it is an array or a sequence.
+                 */
+                List<CommonTree> lengthChildren = length.getChildren();
+
+                CommonTree first = lengthChildren.get(0);
+                if (isUnaryInteger(first)) {
+                    /* Array */
+                    int arrayLength = UnaryIntegerParser.INSTANCE.parse(first, null).intValue();
+
+                    if (arrayLength < 1) {
+                        throw new ParseException("Array length is negative"); //$NON-NLS-1$
+                    }
+
+                    /* Create the array declaration. */
+                    declaration = new ArrayDeclaration(arrayLength, declaration);
+                } else if (isAnyUnaryString(first)) {
+                    /* Sequence */
+                    String lengthName = concatenateUnaryStrings(lengthChildren);
+
+                    /* check that lengthName was declared */
+                    if (isSignedIntegerField(lengthName, scope)) {
+                        throw new ParseException("Sequence declared with length that is not an unsigned integer"); //$NON-NLS-1$
+                    }
+                    /* Create the sequence declaration. */
+                    declaration = new SequenceDeclaration(lengthName,
+                            declaration);
+                } else if (isTrace(first)) {
+                    /* Sequence */
+                    String lengthName = TraceScopeParser.INSTANCE.parse(null, new TraceScopeParser.Param(lengthChildren));
+
+                    /* check that lengthName was declared */
+                    if (isSignedIntegerField(lengthName, scope)) {
+                        throw new ParseException("Sequence declared with length that is not an unsigned integer"); //$NON-NLS-1$
+                    }
+                    /* Create the sequence declaration. */
+                    declaration = new SequenceDeclaration(lengthName,
+                            declaration);
+
+                } else if (isStream(first)) {
+                    /* Sequence */
+                    String lengthName = StreamScopeParser.INSTANCE.parse(null, new StreamScopeParser.Param(lengthChildren));
+
+                    /* check that lengthName was declared */
+                    if (isSignedIntegerField(lengthName, scope)) {
+                        throw new ParseException("Sequence declared with length that is not an unsigned integer"); //$NON-NLS-1$
+                    }
+                    /* Create the sequence declaration. */
+                    declaration = new SequenceDeclaration(lengthName,
+                            declaration);
+                } else if (isEvent(first)) {
+                    /* Sequence */
+                    String lengthName = EventScopeParser.INSTANCE.parse(null, new EventScopeParser.Param(lengthChildren));
+
+                    /* check that lengthName was declared */
+                    if (isSignedIntegerField(lengthName, scope)) {
+                        throw new ParseException("Sequence declared with length that is not an unsigned integer"); //$NON-NLS-1$
+                    }
+                    /* Create the sequence declaration. */
+                    declaration = new SequenceDeclaration(lengthName,
+                            declaration);
+                } else {
+                    throw childTypeError(first);
+                }
+            }
+        }
+
+        if (identifier != null) {
+            final String text = identifier.getText();
+            if (text == null) {
+                throw new ParseException("Cannot have unidentified declarator"); //$NON-NLS-1$
+            }
+            ((Param) param).fBuilder.append(text);
+            registerType(declaration, text, scope);
+        }
+
+        return declaration;
+    }
+
+    private static boolean isSignedIntegerField(String lengthName, DeclarationScope scope) throws ParseException {
+        IDeclaration decl = scope.lookupIdentifierRecursive(lengthName);
+        if (decl instanceof IntegerDeclaration) {
+            return ((IntegerDeclaration) decl).isSigned();
+        }
+        throw new ParseException("Is not an integer: " + lengthName); //$NON-NLS-1$
+
+    }
+
+    private static boolean isEvent(CommonTree first) {
+        return first.getType() == CTFParser.EVENT;
+    }
+
+    private static boolean isStream(CommonTree first) {
+        return first.getType() == CTFParser.STREAM;
+    }
+
+    private static boolean isTrace(CommonTree first) {
+        return first.getType() == CTFParser.TRACE;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeSpecifierListNameParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeSpecifierListNameParser.java
new file mode 100644 (file)
index 0000000..8e03a01
--- /dev/null
@@ -0,0 +1,124 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.childTypeError;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ * Type specifier list name parser (is it a bool? a string... )
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public class TypeSpecifierListNameParser implements ICommonTreeParser {
+
+    /**
+     * Instance
+     */
+    public static final TypeSpecifierListNameParser INSTANCE = new TypeSpecifierListNameParser();
+
+    private TypeSpecifierListNameParser() {
+    }
+
+    /**
+     * Creates the string representation of a type specifier.
+     *
+     * @param typeSpecifier
+     *            A TYPE_SPECIFIER node.
+     *
+     * @return param unused
+     * @throws ParseException
+     *             invalid node
+     */
+    @Override
+    public StringBuilder parse(CommonTree typeSpecifier, ICommonTreeParserParameter param) throws ParseException {
+        StringBuilder sb = new StringBuilder();
+        switch (typeSpecifier.getType()) {
+        case CTFParser.FLOATTOK:
+        case CTFParser.INTTOK:
+        case CTFParser.LONGTOK:
+        case CTFParser.SHORTTOK:
+        case CTFParser.SIGNEDTOK:
+        case CTFParser.UNSIGNEDTOK:
+        case CTFParser.CHARTOK:
+        case CTFParser.DOUBLETOK:
+        case CTFParser.VOIDTOK:
+        case CTFParser.BOOLTOK:
+        case CTFParser.COMPLEXTOK:
+        case CTFParser.IMAGINARYTOK:
+        case CTFParser.CONSTTOK:
+        case CTFParser.IDENTIFIER:
+            parseSimple(typeSpecifier, sb);
+            break;
+        case CTFParser.STRUCT: {
+            parseStruct(typeSpecifier, sb);
+            break;
+        }
+        case CTFParser.VARIANT: {
+            parseVariant(typeSpecifier, sb);
+            break;
+        }
+        case CTFParser.ENUM: {
+            parseEnum(typeSpecifier, sb);
+            break;
+        }
+        case CTFParser.FLOATING_POINT:
+        case CTFParser.INTEGER:
+        case CTFParser.STRING:
+            throw new ParseException("CTF type found in createTypeSpecifierString"); //$NON-NLS-1$
+        default:
+            throw childTypeError(typeSpecifier);
+        }
+        return sb;
+
+    }
+
+    private static void parseEnum(CommonTree typeSpecifier, StringBuilder sb) throws ParseException {
+        CommonTree enumName = (CommonTree) typeSpecifier.getFirstChildWithType(CTFParser.ENUM_NAME);
+        if (enumName == null) {
+            throw new ParseException("nameless enum found in createTypeSpecifierString"); //$NON-NLS-1$
+        }
+
+        CommonTree enumNameIdentifier = (CommonTree) enumName.getChild(0);
+
+        parseSimple(enumNameIdentifier, sb);
+    }
+
+    private static void parseVariant(CommonTree typeSpecifier, StringBuilder sb) throws ParseException {
+        CommonTree variantName = (CommonTree) typeSpecifier.getFirstChildWithType(CTFParser.VARIANT_NAME);
+        if (variantName == null) {
+            throw new ParseException("nameless variant found in createTypeSpecifierString"); //$NON-NLS-1$
+        }
+
+        CommonTree variantNameIdentifier = (CommonTree) variantName.getChild(0);
+
+        parseSimple(variantNameIdentifier, sb);
+    }
+
+    private static void parseSimple(CommonTree typeSpecifier, StringBuilder sb) {
+        sb.append(typeSpecifier.getText());
+    }
+
+    private static void parseStruct(CommonTree typeSpecifier, StringBuilder sb) throws ParseException {
+        CommonTree structName = (CommonTree) typeSpecifier.getFirstChildWithType(CTFParser.STRUCT_NAME);
+        if (structName == null) {
+            throw new ParseException("nameless struct found in createTypeSpecifierString"); //$NON-NLS-1$
+        }
+
+        CommonTree structNameIdentifier = (CommonTree) structName.getChild(0);
+
+        parseSimple(structNameIdentifier, sb);
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeSpecifierListParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeSpecifierListParser.java
new file mode 100644 (file)
index 0000000..06a294b
--- /dev/null
@@ -0,0 +1,168 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.childTypeError;
+
+import java.nio.ByteOrder;
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
+import org.eclipse.tracecompass.ctf.core.event.types.EnumDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.enumeration.EnumParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.floatingpoint.FloatDeclarationParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.integer.IntegerDeclarationParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.string.StringDeclarationParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.struct.StructParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.variant.VariantParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderCompactDeclaration;
+import org.eclipse.tracecompass.internal.ctf.core.event.types.composite.EventHeaderLargeDeclaration;
+
+/**
+ * Parse the specifiers. Make sure they are known types. This can be seen as a
+ * declaration factory.
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public class TypeSpecifierListParser extends AbstractScopedCommonTreeParser {
+
+    /**
+     * Parameter Object
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+        private final DeclarationScope fDeclarationScope;
+        private final @Nullable List<CommonTree> fListNode;
+        private final CTFTrace fTrace;
+        private final @Nullable CommonTree fIdentifier;
+
+        /**
+         * Constructor
+         *
+         * @param trace
+         *            The trace
+         * @param listNode
+         *            A list of POINTER nodes that apply to the specified type.
+         * @param identifier
+         *            the identifier node
+         * @param scope
+         *            the current scope
+         */
+        public Param(CTFTrace trace, @Nullable List<CommonTree> listNode, @Nullable CommonTree identifier, DeclarationScope scope) {
+            fTrace = trace;
+            fListNode = listNode;
+            fIdentifier = identifier;
+            fDeclarationScope = scope;
+        }
+    }
+
+    /**
+     * The instance
+     */
+    public final static TypeSpecifierListParser INSTANCE = new TypeSpecifierListParser();
+
+    private TypeSpecifierListParser() {
+    }
+
+    /**
+     * Parses a type specifier list and returns the corresponding declaration.
+     *
+     * @param typeSpecifierList
+     *            A TYPE_SPECIFIER_LIST node.
+     * @param param
+     *            The paramer object
+     *
+     * @return The corresponding declaration.
+     * @throws ParseException
+     *             If the type has not been defined or if there is an error
+     *             creating the declaration.
+     */
+    @Override
+    public IDeclaration parse(CommonTree typeSpecifierList, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        final DeclarationScope scope = ((Param) param).fDeclarationScope;
+        List<@NonNull CommonTree> pointerList = ((Param) param).fListNode;
+        CTFTrace trace = ((Param) param).fTrace;
+        CommonTree identifier = ((Param) param).fIdentifier;
+        IDeclaration declaration = null;
+
+        /*
+         * By looking at the first element of the type specifier list, we can
+         * determine which type it belongs to.
+         */
+        CommonTree firstChild = (CommonTree) typeSpecifierList.getChild(0);
+
+        switch (firstChild.getType()) {
+        case CTFParser.FLOATING_POINT:
+            declaration = FloatDeclarationParser.INSTANCE.parse(firstChild, new FloatDeclarationParser.Param(trace));
+            break;
+        case CTFParser.INTEGER:
+            declaration = IntegerDeclarationParser.INSTANCE.parse(firstChild, new IntegerDeclarationParser.Param(trace));
+            break;
+        case CTFParser.STRING:
+            declaration = StringDeclarationParser.INSTANCE.parse(firstChild, null);
+            break;
+        case CTFParser.STRUCT:
+            declaration = StructParser.INSTANCE.parse(firstChild, new StructParser.Param(trace, identifier, scope));
+            StructDeclaration structDeclaration = (StructDeclaration) declaration;
+            IDeclaration idEnumDecl = structDeclaration.getFields().get("id"); //$NON-NLS-1$
+            if (idEnumDecl instanceof EnumDeclaration) {
+                EnumDeclaration enumDeclaration = (EnumDeclaration) idEnumDecl;
+                ByteOrder bo = enumDeclaration.getContainerType().getByteOrder();
+                if (EventHeaderCompactDeclaration.getEventHeader(bo).isCompactEventHeader(structDeclaration)) {
+                    declaration = EventHeaderCompactDeclaration.getEventHeader(bo);
+                } else if (EventHeaderLargeDeclaration.getEventHeader(bo).isLargeEventHeader(structDeclaration)) {
+                    declaration = EventHeaderLargeDeclaration.getEventHeader(bo);
+                }
+            }
+            break;
+        case CTFParser.VARIANT:
+            declaration = VariantParser.INSTANCE.parse(firstChild, new VariantParser.Param(trace, scope));
+            break;
+        case CTFParser.ENUM:
+            declaration = EnumParser.INSTANCE.parse(firstChild, new EnumParser.Param(trace, scope));
+            break;
+        case CTFParser.IDENTIFIER:
+        case CTFParser.FLOATTOK:
+        case CTFParser.INTTOK:
+        case CTFParser.LONGTOK:
+        case CTFParser.SHORTTOK:
+        case CTFParser.SIGNEDTOK:
+        case CTFParser.UNSIGNEDTOK:
+        case CTFParser.CHARTOK:
+        case CTFParser.DOUBLETOK:
+        case CTFParser.VOIDTOK:
+        case CTFParser.BOOLTOK:
+        case CTFParser.COMPLEXTOK:
+        case CTFParser.IMAGINARYTOK:
+            declaration = TypeDeclarationParser.INSTANCE.parse(typeSpecifierList, new TypeDeclarationParser.Param(pointerList, scope));
+            break;
+        default:
+            throw childTypeError(firstChild);
+        }
+
+        return declaration;
+    }
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeSpecifierListStringParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypeSpecifierListStringParser.java
new file mode 100644 (file)
index 0000000..84e70aa
--- /dev/null
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ * Type specifier list string parser, parses a list of names
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public class TypeSpecifierListStringParser implements ICommonTreeParser {
+
+    /**
+     * Instance
+     */
+    public static final TypeSpecifierListStringParser INSTANCE = new TypeSpecifierListStringParser();
+
+    private TypeSpecifierListStringParser() {
+    }
+
+    /**
+     * Creates the string representation of a type specifier.
+     *
+     * @param typeSpecifierList
+     *            A TYPE_SPECIFIER node.
+     * @param param
+     *            unused
+     *
+     * @return A StringBuilder to which will be appended the string.
+     * @throws ParseException
+     *             invalid node
+     */
+    @Override
+    public StringBuilder parse(CommonTree typeSpecifierList, ICommonTreeParserParameter param) throws ParseException {
+        StringBuilder sb = new StringBuilder();
+        List<CommonTree> children = typeSpecifierList.getChildren();
+
+        boolean firstItem = true;
+
+        for (CommonTree child : children) {
+            if (!firstItem) {
+                sb.append(' ');
+
+            }
+
+            firstItem = false;
+
+            /* Append the string that represents this type specifier. */
+            sb.append(TypeSpecifierListNameParser.INSTANCE.parse(child, null));
+        }
+        return sb;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypedefParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/TypedefParser.java
new file mode 100644 (file)
index 0000000..1218684
--- /dev/null
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.VariantDeclaration;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ * C typedef parser
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public class TypedefParser extends AbstractScopedCommonTreeParser {
+
+    /**
+     * Parameter object with a trace and current scope
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+        private final DeclarationScope fDeclarationScope;
+        private final CTFTrace fTrace;
+
+        /**
+         * Constructor
+         *
+         * @param trace
+         *            the trace
+         * @param scope
+         *            the current scope
+         */
+        public Param(CTFTrace trace, DeclarationScope scope) {
+            fTrace = trace;
+            fDeclarationScope = scope;
+        }
+    }
+
+    /**
+     * The instance
+     */
+    public final static TypedefParser INSTANCE = new TypedefParser();
+
+    private TypedefParser() {
+    }
+
+    /**
+     * Parses a typedef node. This creates and registers a new declaration for
+     * each declarator found in the typedef.
+     *
+     * @param typedef
+     *            A TYPEDEF node.
+     *
+     * @return map of type name to type declaration
+     * @throws ParseException
+     *             If there is an error creating the declaration.
+     */
+    @Override
+    public Map<String, IDeclaration> parse(CommonTree typedef, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        DeclarationScope scope = ((Param) param).fDeclarationScope;
+
+        CommonTree typeDeclaratorListNode = (CommonTree) typedef.getFirstChildWithType(CTFParser.TYPE_DECLARATOR_LIST);
+        if (typeDeclaratorListNode == null) {
+            throw new ParseException("Cannot have a typedef without a declarator"); //$NON-NLS-1$
+        }
+        CommonTree typeSpecifierListNode = (CommonTree) typedef.getFirstChildWithType(CTFParser.TYPE_SPECIFIER_LIST);
+        if (typeSpecifierListNode == null) {
+            throw new ParseException("Cannot have a typedef without specifiers"); //$NON-NLS-1$
+        }
+        List<CommonTree> typeDeclaratorList = typeDeclaratorListNode.getChildren();
+
+        Map<String, IDeclaration> declarations = new HashMap<>();
+
+        for (CommonTree typeDeclaratorNode : typeDeclaratorList) {
+            StringBuilder identifierSB = new StringBuilder();
+            CTFTrace trace = ((Param) param).fTrace;
+            IDeclaration typeDeclaration = TypeDeclaratorParser.INSTANCE.parse(typeDeclaratorNode, new TypeDeclaratorParser.Param(trace, typeSpecifierListNode, scope, identifierSB));
+
+            if ((typeDeclaration instanceof VariantDeclaration)
+                    && !((VariantDeclaration) typeDeclaration).isTagged()) {
+                throw new ParseException("Typealias of untagged variant is not permitted"); //$NON-NLS-1$
+            }
+
+            scope.registerType(identifierSB.toString(), typeDeclaration);
+
+            declarations.put(identifierSB.toString(), typeDeclaration);
+        }
+        return declarations;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/UnaryIntegerParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/UnaryIntegerParser.java
new file mode 100644 (file)
index 0000000..f367937
--- /dev/null
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ * Unary Integer Parser, along with Unary string parser, one of the two most
+ * used parsers in TSDL. Converts a string representation of an integer into a
+ * java {@link Long}
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public final class UnaryIntegerParser implements ICommonTreeParser {
+
+    /**
+     * Instance
+     */
+    public static final UnaryIntegerParser INSTANCE = new UnaryIntegerParser();
+
+    private UnaryIntegerParser() {
+    }
+
+    /**
+     * Parses an unary integer (dec, hex or oct).
+     *
+     * @param unaryInteger
+     *            An unary integer node.
+     *
+     * @return The integer value.
+     * @throws ParseException
+     *             on an invalid integer format ("bob" for example)
+     */
+    @Override
+    public Long parse(CommonTree unaryInteger, ICommonTreeParserParameter notUsed) throws ParseException {
+        List<CommonTree> children = unaryInteger.getChildren();
+        CommonTree value = children.get(0);
+        String strval = value.getText();
+
+        long intval;
+        try {
+            intval = Long.decode(strval);
+        } catch (NumberFormatException e) {
+            throw new ParseException("Invalid integer format: " + strval, e); //$NON-NLS-1$
+        }
+
+        /* The rest of children are sign */
+        if ((children.size() % 2) == 0) {
+            return -intval;
+        }
+        return intval;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/UnaryStringParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/UnaryStringParser.java
new file mode 100644 (file)
index 0000000..0eb8aaf
--- /dev/null
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ * Unary String Parser, along with Unary integer parser, one of the two most
+ * used parsers in TSDL. Takes a basic node of the AST and converts it to a java
+ * {@link String}.]
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public final class UnaryStringParser implements ICommonTreeParser {
+
+    /** Instance */
+    public static final UnaryStringParser INSTANCE = new UnaryStringParser();
+
+    private UnaryStringParser() {
+    }
+
+    /**
+     * Parses a unary string node and return the string value.
+     *
+     * @param unaryString
+     *            The unary string node to parse (type UNARY_EXPRESSION_STRING
+     *            or UNARY_EXPRESSION_STRING_QUOTES).
+     *
+     * @return The string value.
+     * @throws ParseException
+     *             The tree node (unaryString) is not a unary string.
+     */
+    /*
+     * It would be really nice to remove the quotes earlier, such as in the
+     * parser.
+     */
+    @Override
+    public String parse(CommonTree unaryString, ICommonTreeParserParameter notUsed) throws ParseException {
+        CommonTree value = (CommonTree) unaryString.getChild(0);
+        if (value.getType() == CTFParser.UNARY_EXPRESSION_STRING) {
+            value = (CommonTree) value.getChild(0);
+        }
+        String strval = value.getText();
+        if (strval == null) {
+            throw new ParseException("Unary String was null"); //$NON-NLS-1$
+        }
+
+        /* Remove quotes */
+        if (unaryString.getType() == CTFParser.UNARY_EXPRESSION_STRING_QUOTES) {
+            strval = strval.substring(1, strval.length() - 1);
+        }
+
+        return strval;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/enumeration/EnumBodyParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/enumeration/EnumBodyParser.java
new file mode 100644 (file)
index 0000000..e8b9044
--- /dev/null
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.enumeration;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.core.event.types.EnumDeclaration;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ * Body parser for an enumeration, this parses the list of elements in an enum
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public class EnumBodyParser implements ICommonTreeParser {
+
+    /**
+     * Enum declaration parameter object
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+
+        private final EnumDeclaration fEnumDeclaration;
+
+        /**
+         * Constructor
+         *
+         * @param enumDeclaration
+         *            the enumeration
+         */
+        public Param(EnumDeclaration enumDeclaration) {
+            fEnumDeclaration = enumDeclaration;
+        }
+
+    }
+
+    /**
+     * The instance
+     */
+    public static final EnumBodyParser INSTANCE = new EnumBodyParser();
+
+    private EnumBodyParser() {
+    }
+
+    @Override
+    public EnumDeclaration parse(CommonTree tree, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        Param parameter = (Param) param;
+        EnumDeclaration enumDeclaration = parameter.fEnumDeclaration;
+        List<CommonTree> enumerators = tree.getChildren();
+        /*
+         * Start at -1, so that if the first enumrator has no explicit value, it
+         * will choose 0
+         */
+        for (CommonTree enumerator : enumerators) {
+            EnumeratorParser.INSTANCE.parse(enumerator, new EnumeratorParser.Param(enumDeclaration));
+        }
+        return enumDeclaration;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/enumeration/EnumContainerParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/enumeration/EnumContainerParser.java
new file mode 100644 (file)
index 0000000..9b41de9
--- /dev/null
@@ -0,0 +1,99 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.enumeration;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TypeSpecifierListParser;
+
+/**
+ * This parses the internal type of the enum
+ *
+ * @author Matthew Khouzam - Initial implementation and API
+ *
+ */
+public class EnumContainerParser extends AbstractScopedCommonTreeParser {
+
+    /**
+     * Parameter object with a trace and scope
+     *
+     * @author Matthew Khouzam
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+
+        private final DeclarationScope fCurrentScope;
+        private final CTFTrace fTrace;
+
+        /**
+         * Constructor
+         *
+         * @param trace
+         *            the trace
+         * @param currentScope
+         *            the scope
+         */
+        public Param(CTFTrace trace, DeclarationScope currentScope) {
+            fTrace = trace;
+            fCurrentScope = currentScope;
+        }
+
+    }
+
+    /**
+     * The instance
+     */
+    public static final EnumContainerParser INSTANCE = new EnumContainerParser();
+
+    private EnumContainerParser() {
+    }
+
+    /**
+     * Parses an enum container type node and returns the corresponding integer
+     * type.
+     *
+     * @param enumContainerType
+     *            An ENUM_CONTAINER_TYPE node.
+     *
+     * @return An integer declaration corresponding to the container type.
+     * @throws ParseException
+     *             If the type does not parse correctly or if it is not an
+     *             integer type.
+     */
+    @Override
+    public IntegerDeclaration parse(CommonTree enumContainerType, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        Param parameter = (Param) param;
+        DeclarationScope scope = parameter.fCurrentScope;
+
+        /* Get the child, which should be a type specifier list */
+        CommonTree typeSpecifierList = (CommonTree) enumContainerType.getChild(0);
+
+        CTFTrace trace = ((Param) param).fTrace;
+        /* Parse it and get the corresponding declaration */
+        IDeclaration decl = TypeSpecifierListParser.INSTANCE.parse(typeSpecifierList, new TypeSpecifierListParser.Param(trace, null, null, scope));
+
+        /* If is is an integer, return it, else throw an error */
+        if (decl instanceof IntegerDeclaration) {
+            return (IntegerDeclaration) decl;
+        }
+        throw new ParseException("enum container type must be an integer"); //$NON-NLS-1$
+
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/enumeration/EnumParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/enumeration/EnumParser.java
new file mode 100644 (file)
index 0000000..17ac03a
--- /dev/null
@@ -0,0 +1,262 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.enumeration;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.childTypeError;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
+import org.eclipse.tracecompass.ctf.core.event.types.EnumDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ *
+ * Enumerations are a mapping between an integer type and a table of strings.
+ * The numerical representation of the enumeration follows the integer type
+ * specified by the metadata. The enumeration mapping table is detailed in the
+ * enumeration description within the metadata. The mapping table maps inclusive
+ * value ranges (or single values) to strings. Instead of being limited to
+ * simple `value -> string` mappings, these enumerations map `[ start_value ...
+ * end_value ] -> string`, which map inclusive ranges of values to strings. An
+ * enumeration from the C language can be represented in this format by having
+ * the same `start_value` and `end_value` for each mapping, which is in fact a
+ * range of size 1. This single-value range is supported without repeating the
+ * start and end values with the `value = string` declaration. Enumerations need
+ * to contain at least one entry. <br>
+ *
+ * <pre>
+enum name : integer_type {
+    somestring          =  start_value1 ... end_value1 ,
+    "other string"      = start_value2 ... end_value2 ,
+    yet_another_string,   will be assigned to end_value2 + 1 ,
+    "some other string" = value,
+    //...
+}
+ * </pre>
+ *
+ * If the values are omitted, the enumeration starts at 0 and increment of 1 for
+ * each entry. An entry with omitted value that follows a range entry takes as
+ * value the `end_value` of the previous range + 1:
+ *
+ * <pre>
+enum name : unsigned int {
+ ZERO,
+ ONE,
+ TWO,
+ TEN = 10,
+ ELEVEN,
+}
+ * </pre>
+ *
+ * Overlapping ranges within a single enumeration are implementation defined.
+ * <br>
+ * A nameless enumeration can be declared as a field type or as part of a
+ * `typedef`:
+ *
+ * <pre>
+enum : integer_type {
+ // ...
+}
+ * </pre>
+ *
+ * Enumerations omitting the container type`:integer_type`use the`int`type(for
+ * compatibility with C99).The`int`type _must be_ previously declared,e.g.:
+ *
+ * <pre>
+ * typealias integer{size=32;align=32;signed=true;}:=int;
+
+enum{
+// ...
+}
+ * </pre>
+ *
+ * @author Matthew Khouzam
+ * @author Efficios - Description
+ *
+ */
+public class EnumParser extends AbstractScopedCommonTreeParser {
+
+    /**
+     * Parameter Object
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+
+        private final DeclarationScope fCurrentScope;
+        private final CTFTrace fTrace;
+
+        /**
+         * Parameter object constructor
+         *
+         * @param trace
+         *            Trace to populate
+         * @param currentScope
+         *            the current scope
+         */
+        public Param(CTFTrace trace, DeclarationScope currentScope) {
+            fTrace = trace;
+            fCurrentScope = currentScope;
+        }
+
+    }
+
+    /**
+     * Instance
+     */
+    public static final EnumParser INSTANCE = new EnumParser();
+
+    private EnumParser() {
+    }
+
+    /**
+     * Parses an enum declaration and returns the corresponding declaration.
+     *
+     * @param theEnum
+     *            An ENUM node.
+     *
+     * @return The corresponding enum declaration.
+     * @throws ParseException
+     *             there was an error parsing the enum. Probably a mal-formed
+     *             tree.
+     */
+    @Override
+    public EnumDeclaration parse(CommonTree theEnum, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        Param parameter = (Param) param;
+        DeclarationScope scope = parameter.fCurrentScope;
+
+        List<CommonTree> children = theEnum.getChildren();
+
+        /* The return value */
+        EnumDeclaration enumDeclaration = null;
+
+        /* Name */
+        String enumName = null;
+
+        /* Body */
+        CommonTree enumBody = null;
+
+        /* Container type */
+        IntegerDeclaration containerTypeDeclaration = null;
+
+        /* Loop on all children and identify what we have to work with. */
+        for (CommonTree child : children) {
+            switch (child.getType()) {
+            case CTFParser.ENUM_NAME: {
+                CommonTree enumNameIdentifier = (CommonTree) child.getChild(0);
+                enumName = enumNameIdentifier.getText();
+                break;
+            }
+            case CTFParser.ENUM_BODY: {
+                enumBody = child;
+                break;
+            }
+            case CTFParser.ENUM_CONTAINER_TYPE: {
+                CTFTrace trace = ((Param) param).fTrace;
+                containerTypeDeclaration = EnumContainerParser.INSTANCE.parse(child, new EnumContainerParser.Param(trace, scope));
+                break;
+            }
+            default:
+                throw childTypeError(child);
+            }
+        }
+
+        /*
+         * If the container type has not been defined explicitly, we assume it
+         * is "int".
+         */
+        if (containerTypeDeclaration == null) {
+            IDeclaration enumDecl;
+            /*
+             * it could be because the enum was already declared.
+             */
+            if (enumName != null) {
+                scope.setName(enumName);
+                enumDecl = scope.lookupEnumRecursive(enumName);
+                if (enumDecl != null) {
+                    return (EnumDeclaration) enumDecl;
+                }
+            }
+
+            IDeclaration decl = scope.lookupTypeRecursive("int"); //$NON-NLS-1$
+
+            if (decl == null) {
+                throw new ParseException("enum container type implicit and type int not defined"); //$NON-NLS-1$
+            } else if (!(decl instanceof IntegerDeclaration)) {
+                throw new ParseException("enum container type implicit and type int not an integer"); //$NON-NLS-1$
+            }
+
+            containerTypeDeclaration = (IntegerDeclaration) decl;
+        }
+
+        /*
+         * If it has a body, it's a new declaration, otherwise it's a reference
+         * to an existing declaration. Same logic as struct.
+         */
+        if (enumBody != null) {
+            /*
+             * If enum has a name, check if already defined in the current
+             * scope.
+             */
+            if ((enumName != null)
+                    && (scope.lookupEnum(enumName) != null)) {
+                throw new ParseException("enum " + enumName //$NON-NLS-1$
+                        + " already defined"); //$NON-NLS-1$
+            }
+
+            /* Create the declaration */
+            enumDeclaration = new EnumDeclaration(containerTypeDeclaration);
+
+            /* Parse the body */
+            EnumBodyParser.INSTANCE.parse(enumBody, new EnumBodyParser.Param(enumDeclaration));
+
+            /* If the enum has name, add it to the current scope. */
+            if (enumName != null) {
+                scope.registerEnum(enumName, enumDeclaration);
+            }
+        } else {
+            if (enumName != null) {
+                /* Name and !body */
+
+                /* Lookup the name in the current scope. */
+                enumDeclaration = scope.lookupEnumRecursive(enumName);
+
+                /*
+                 * If not found, it means that an enum with such name has not
+                 * been defined
+                 */
+                if (enumDeclaration == null) {
+                    throw new ParseException("enum " + enumName //$NON-NLS-1$
+                            + " is not defined"); //$NON-NLS-1$
+                }
+            } else {
+                /* !Name and !body */
+                throw new ParseException("enum with no name and no body"); //$NON-NLS-1$
+            }
+        }
+
+        return enumDeclaration;
+
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/enumeration/EnumeratorParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/enumeration/EnumeratorParser.java
new file mode 100644 (file)
index 0000000..077ae29
--- /dev/null
@@ -0,0 +1,130 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.enumeration;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.childTypeError;
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isAnyUnaryString;
+
+import java.math.BigInteger;
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.core.event.types.EnumDeclaration;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.UnaryIntegerParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.UnaryStringParser;
+
+/**
+ * The parser for individual enumerators within an enum body
+ *
+ * @author Matthew Khouzam - Initial API and implementation
+ *
+ */
+public final class EnumeratorParser implements ICommonTreeParser {
+
+    /**
+     * A parameter containing an enum declaration
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+        private final EnumDeclaration fEnumDeclaration;
+
+        /**
+         * Constructor
+         *
+         * @param enumDeclaration
+         *            the enum declaration to populate
+         */
+        public Param(EnumDeclaration enumDeclaration) {
+            fEnumDeclaration = enumDeclaration;
+        }
+    }
+
+    /**
+     * Instance
+     */
+    public static final EnumeratorParser INSTANCE = new EnumeratorParser();
+
+    private EnumeratorParser() {
+    }
+
+    /**
+     * Parses an enumerator node and adds an enumerator declaration to an
+     * enumeration declaration.
+     *
+     * The high value of the range of the last enumerator is needed in case the
+     * current enumerator does not specify its value.
+     *
+     * @param enumerator
+     *            An ENUM_ENUMERATOR node.
+     * @param param
+     *            an enumeration declaration to which will be added the
+     *            enumerator.
+     * @return The high value of the value range of the current enumerator.
+     * @throws ParseException
+     *             if the element failed to add
+     */
+    @Override
+    public Long parse(CommonTree enumerator, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        EnumDeclaration enumDeclaration = ((Param) param).fEnumDeclaration;
+
+        List<CommonTree> children = enumerator.getChildren();
+
+        long low = 0, high = 0;
+        boolean valueSpecified = false;
+        String label = null;
+
+        for (CommonTree child : children) {
+            if (isAnyUnaryString(child)) {
+                label = UnaryStringParser.INSTANCE.parse(child, null);
+            } else if (child.getType() == CTFParser.ENUM_VALUE) {
+
+                valueSpecified = true;
+
+                low = UnaryIntegerParser.INSTANCE.parse((CommonTree) child.getChild(0), null);
+                high = low;
+            } else if (child.getType() == CTFParser.ENUM_VALUE_RANGE) {
+
+                valueSpecified = true;
+
+                low = UnaryIntegerParser.INSTANCE.parse((CommonTree) child.getChild(0), null);
+                high = UnaryIntegerParser.INSTANCE.parse((CommonTree) child.getChild(1), null);
+            } else {
+                throw childTypeError(child);
+            }
+        }
+
+        if (low > high) {
+            throw new ParseException("enum low value greater than high value"); //$NON-NLS-1$
+        }
+        if (valueSpecified && !enumDeclaration.add(low, high, label)) {
+            throw new ParseException("enum declarator values overlap."); //$NON-NLS-1$
+        } else if (!valueSpecified && !enumDeclaration.add(label)) {
+            throw new ParseException("enum cannot add element " + label); //$NON-NLS-1$
+        }
+
+        if (valueSpecified && (BigInteger.valueOf(low).compareTo(enumDeclaration.getContainerType().getMinValue()) == -1 ||
+                BigInteger.valueOf(high).compareTo(enumDeclaration.getContainerType().getMaxValue()) == 1)) {
+            throw new ParseException("enum value is not in range"); //$NON-NLS-1$
+        }
+
+        return high;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/environment/EnvironmentParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/environment/EnvironmentParser.java
new file mode 100644 (file)
index 0000000..25269f5
--- /dev/null
@@ -0,0 +1,50 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.environment;
+
+import java.util.List;
+import java.util.Map;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * A scope containing pairs of values that are immutable to the trace.
+ *
+ * @author Matthew Khouzam - Initial API and implementation
+ *
+ */
+public final class EnvironmentParser implements ICommonTreeParser {
+
+    /**
+     * The instance
+     */
+    public static final EnvironmentParser INSTANCE = new EnvironmentParser();
+
+    private EnvironmentParser() {
+    }
+
+    @Override
+    public Map<String, String> parse(CommonTree environment, ICommonTreeParserParameter param) {
+
+        ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<>();
+        List<CommonTree> children = environment.getChildren();
+        for (CommonTree child : children) {
+            String left;
+            String right;
+            left = child.getChild(0).getChild(0).getChild(0).getText();
+            right = child.getChild(1).getChild(0).getChild(0).getText();
+            builder.put(left, right);
+        }
+        return builder.build();
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/event/EventDeclarationParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/event/EventDeclarationParser.java
new file mode 100644 (file)
index 0000000..5ca4031
--- /dev/null
@@ -0,0 +1,192 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.event;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.concatenateUnaryStrings;
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isAnyUnaryString;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TypeSpecifierListParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.UnaryIntegerParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.UnaryStringParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.stream.StreamIdParser;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
+
+/**
+ * The declaration of an event
+ *
+ * @author Matthew Khouzam - Initial API and implementation
+ *
+ */
+public final class EventDeclarationParser extends AbstractScopedCommonTreeParser {
+
+    /**
+     * Parameter object, contains a trace, an event and a scope
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+        private final EventDeclaration fEvent;
+        private final CTFTrace fTrace;
+        private final DeclarationScope fDeclarationScope;
+
+        /**
+         * Constructor
+         *
+         * @param trace
+         *            the trace
+         * @param event
+         *            the event to populate
+         * @param scope
+         *            the current scope
+         */
+        public Param(CTFTrace trace, EventDeclaration event, DeclarationScope scope) {
+            fTrace = trace;
+            fEvent = event;
+            fDeclarationScope = scope;
+        }
+
+    }
+
+    /**
+     * Instance
+     */
+    public static final EventDeclarationParser INSTANCE = new EventDeclarationParser();
+
+    private EventDeclarationParser() {
+    }
+
+    @Override
+    public EventDeclaration parse(CommonTree eventDecl, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        DeclarationScope scope = ((Param) param).fDeclarationScope;
+        EventDeclaration event = ((Param) param).fEvent;
+        CTFTrace fTrace = ((Param) param).fTrace;
+
+        /* There should be a left and right */
+
+        CommonTree leftNode = (CommonTree) eventDecl.getChild(0);
+        CommonTree rightNode = (CommonTree) eventDecl.getChild(1);
+
+        List<CommonTree> leftStrings = leftNode.getChildren();
+
+        if (!isAnyUnaryString(leftStrings.get(0))) {
+            throw new ParseException("Left side of CTF assignment must be a string"); //$NON-NLS-1$
+        }
+
+        String left = concatenateUnaryStrings(leftStrings);
+
+        if (left.equals(MetadataStrings.NAME2)) {
+            if (event.nameIsSet()) {
+                throw new ParseException("name already defined"); //$NON-NLS-1$
+            }
+
+            String name = EventNameParser.INSTANCE.parse(rightNode, null);
+
+            event.setName(name);
+        } else if (left.equals(MetadataStrings.ID)) {
+            if (event.idIsSet()) {
+                throw new ParseException("id already defined"); //$NON-NLS-1$
+            }
+
+            long id = EventIDParser.INSTANCE.parse(rightNode, null);
+            if (id > Integer.MAX_VALUE) {
+                throw new ParseException("id is greater than int.maxvalue, unsupported. id : " + id); //$NON-NLS-1$
+            }
+            if (id < 0) {
+                throw new ParseException("negative id, unsupported. id : " + id); //$NON-NLS-1$
+            }
+            event.setId((int) id);
+        } else if (left.equals(MetadataStrings.STREAM_ID)) {
+            if (event.streamIsSet()) {
+                throw new ParseException("stream id already defined"); //$NON-NLS-1$
+            }
+
+            long streamId = StreamIdParser.INSTANCE.parse(rightNode, null);
+
+            /*
+             * If the event has a stream and it is defined, look up the stream,
+             * if it is the available, assign it. If not, the event is
+             * malformed.
+             */
+            ICTFStream iStream = fTrace.getStream(streamId);
+            if (!(iStream instanceof CTFStream)) {
+                throw new ParseException("Event specified stream with ID " + streamId + ". But no stream with that ID was defined"); //$NON-NLS-1$ //$NON-NLS-2$
+            }
+            CTFStream ctfStream = (CTFStream) iStream;
+            event.setStream(ctfStream);
+        } else if (left.equals(MetadataStrings.CONTEXT)) {
+            if (event.contextIsSet()) {
+                throw new ParseException("context already defined"); //$NON-NLS-1$
+            }
+
+            CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
+
+            if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
+                throw new ParseException("context expects a type specifier"); //$NON-NLS-1$
+            }
+
+            IDeclaration contextDecl = TypeSpecifierListParser.INSTANCE.parse(typeSpecifier, new TypeSpecifierListParser.Param(fTrace, null, null, scope));
+
+            if (!(contextDecl instanceof StructDeclaration)) {
+                throw new ParseException("context expects a struct"); //$NON-NLS-1$
+            }
+
+            event.setContext((StructDeclaration) contextDecl);
+        } else if (left.equals(MetadataStrings.FIELDS_STRING)) {
+            if (event.fieldsIsSet()) {
+                throw new ParseException("fields already defined"); //$NON-NLS-1$
+            }
+
+            CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
+
+            if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
+                throw new ParseException("fields expects a type specifier"); //$NON-NLS-1$
+            }
+
+            IDeclaration fieldsDecl;
+            fieldsDecl = TypeSpecifierListParser.INSTANCE.parse(typeSpecifier, new TypeSpecifierListParser.Param(fTrace, null, null, scope));
+
+            if (!(fieldsDecl instanceof StructDeclaration)) {
+                throw new ParseException("fields expects a struct"); //$NON-NLS-1$
+            }
+            /*
+             * The underscores in the event names. These underscores were added
+             * by the LTTng tracer.
+             */
+            final StructDeclaration fields = (StructDeclaration) fieldsDecl;
+            event.setFields(fields);
+        } else if (left.equals(MetadataStrings.LOGLEVEL2)) {
+            long logLevel = UnaryIntegerParser.INSTANCE.parse((CommonTree) rightNode.getChild(0), null);
+            event.setLogLevel(logLevel);
+        } else {
+            /* Custom event attribute, we'll add it to the attributes map */
+            String right = UnaryStringParser.INSTANCE.parse((CommonTree) rightNode.getChild(0), null);
+            event.setCustomAttribute(left, right);
+        }
+        return event;
+    }
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/event/EventIDParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/event/EventIDParser.java
new file mode 100644 (file)
index 0000000..45c6ae2
--- /dev/null
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.event;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isUnaryInteger;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.UnaryIntegerParser;
+
+/**
+ * An event identifier (ID) relates to the class (a type) of event within an
+ * event stream, e.g. event irq_entry.
+ *
+ * @author Matthew Khouzam - Initial API and implementation
+ * @author Efficios - Description
+ *
+ */
+public final class EventIDParser implements ICommonTreeParser {
+
+    private static final String INVALID_VALUE_ERROR = "Invalid value for event id"; //$NON-NLS-1$
+
+    /**
+     * The instance
+     */
+    public static final EventIDParser INSTANCE = new EventIDParser();
+
+    private EventIDParser() {
+    }
+
+    @Override
+    public Long parse(CommonTree tree, ICommonTreeParserParameter param) throws ParseException {
+
+        CommonTree firstChild = (CommonTree) tree.getChild(0);
+
+        if (isUnaryInteger(firstChild)) {
+            if (tree.getChildCount() > 1) {
+                throw new ParseException(INVALID_VALUE_ERROR);
+            }
+            long intval = UnaryIntegerParser.INSTANCE.parse(firstChild, null);
+            if (intval > Integer.MAX_VALUE) {
+                throw new ParseException("Event id larger than int.maxvalue, something is amiss"); //$NON-NLS-1$
+            }
+            return intval;
+        }
+        throw new ParseException(INVALID_VALUE_ERROR);
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/event/EventNameParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/event/EventNameParser.java
new file mode 100644 (file)
index 0000000..e209e35
--- /dev/null
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.event;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.concatenateUnaryStrings;
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isAnyUnaryString;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ * Parser for event names
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public class EventNameParser implements ICommonTreeParser {
+    /**
+     * Instance
+     */
+    public static final EventNameParser INSTANCE = new EventNameParser();
+
+    private EventNameParser() {
+    }
+
+    @Override
+    public String parse(CommonTree tree, ICommonTreeParserParameter param) throws ParseException {
+        CommonTree firstChild = (CommonTree) tree.getChild(0);
+
+        if (isAnyUnaryString(firstChild)) {
+            return concatenateUnaryStrings(tree.getChildren());
+        }
+        throw new ParseException("invalid value for event name"); //$NON-NLS-1$
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/event/EventParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/event/EventParser.java
new file mode 100644 (file)
index 0000000..999f3c4
--- /dev/null
@@ -0,0 +1,164 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.event;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.childTypeError;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TypeAliasParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TypedefParser;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
+
+/**
+ *
+ *
+ * An event stream can be divided into contiguous event packets of variable
+ * size. An event packet can contain a certain amount of padding at the end. The
+ * stream header is repeated at the beginning of each event packet. The
+ * rationale for the event stream design choices is explained in Stream header
+ * rationale.
+ * <p>
+ * The event stream header will therefore be referred to as the event packet
+ * header throughout the rest of this document.
+ *
+ * @author Matthew Khouzam - Initial API and implementation
+ * @author Efficios - Documentation
+ *
+ */
+public class EventParser extends AbstractScopedCommonTreeParser {
+
+    /**
+     * Parameter object with trace and scope
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+
+        private final DeclarationScope fCurrentScope;
+        private final CTFTrace fTrace;
+
+        /**
+         * Constructor
+         *
+         * @param trace
+         *            the trace
+         * @param currentScope
+         *            the scope
+         */
+        public Param(CTFTrace trace, DeclarationScope currentScope) {
+            fTrace = trace;
+            fCurrentScope = currentScope;
+        }
+
+    }
+
+    /**
+     * The instance
+     */
+    public static final EventParser INSTANCE = new EventParser();
+
+    private EventParser() {
+    }
+
+    /**
+     * Parses an enum declaration and returns the corresponding declaration.
+     *
+     * @param eventNode
+     *            An event node.
+     * @param param
+     *            the parameter object
+     *
+     * @return The corresponding enum declaration.
+     * @throws ParseException
+     *             event stream was badly defined
+     */
+    @Override
+    public EventDeclaration parse(CommonTree eventNode, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        Param parameter = (Param) param;
+        CTFTrace trace = ((Param) param).fTrace;
+        List<CommonTree> children = eventNode.getChildren();
+        if (children == null) {
+            throw new ParseException("Empty event block"); //$NON-NLS-1$
+        }
+
+        EventDeclaration event = new EventDeclaration();
+
+        DeclarationScope scope = new DeclarationScope(parameter.fCurrentScope, MetadataStrings.EVENT);
+
+        for (CommonTree child : children) {
+            switch (child.getType()) {
+            case CTFParser.TYPEALIAS:
+                TypeAliasParser.INSTANCE.parse(child, new TypeAliasParser.Param(trace, scope));
+                break;
+            case CTFParser.TYPEDEF:
+                TypedefParser.INSTANCE.parse(child, new TypedefParser.Param(trace, scope));
+                break;
+            case CTFParser.CTF_EXPRESSION_TYPE:
+            case CTFParser.CTF_EXPRESSION_VAL:
+                EventDeclarationParser.INSTANCE.parse(child, new EventDeclarationParser.Param(trace, event, scope));
+                break;
+            default:
+                throw childTypeError(child);
+            }
+        }
+
+        if (!event.nameIsSet()) {
+            throw new ParseException("Event name not set"); //$NON-NLS-1$
+        }
+
+        /*
+         * If the event did not specify a stream, then the trace must be single
+         * stream
+         */
+        if (!event.streamIsSet()) {
+            if (trace.nbStreams() > 1) {
+                throw new ParseException("Event without stream_id with more than one stream"); //$NON-NLS-1$
+            }
+
+            /*
+             * If the event did not specify a stream, the only existing stream
+             * must not have an id. Note: That behavior could be changed, it
+             * could be possible to just get the only existing stream, whatever
+             * is its id.
+             */
+            ICTFStream iStream = trace.getStream(null);
+            if (iStream instanceof CTFStream) {
+                CTFStream ctfStream = (CTFStream) iStream;
+                event.setStream(ctfStream);
+            } else {
+                throw new ParseException("Event without stream_id, but there is no stream without id"); //$NON-NLS-1$
+            }
+        }
+
+        /*
+         * Add the event to the stream.
+         */
+        event.getStream().addEvent(event);
+
+        return event;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/event/EventScopeParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/event/EventScopeParser.java
new file mode 100644 (file)
index 0000000..97b72ea
--- /dev/null
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.event;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.concatenateUnaryStrings;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ * A local static scope consists in the scope generated by the declaration of
+ * fields within a compound type. A static scope is a local static scope
+ * augmented with the nested sub-static-scopes it contains.
+ * <p>
+ * A dynamic scope consists in the static scope augmented with the implicit
+ * event structure definition hierarchy.
+ * <p>
+ * Multiple declarations of the same field name within a local static scope is
+ * not valid. It is however valid to re-use the same field name in different
+ * local scopes.
+ * <p>
+ * Nested static and dynamic scopes form lookup paths. These are used for
+ * variant tag and sequence length references. They are used at the variant and
+ * sequence definition site to look up the location of the tag field associated
+ * with a variant, and to lookup up the location of the length field associated
+ * with a sequence.
+ * <p>
+ * Variants and sequences can refer to a tag field either using a relative path
+ * or an absolute path. The relative path is relative to the scope in which the
+ * variant or sequence performing the lookup is located. Relative paths are only
+ * allowed to lookup within the same static scope, which includes its nested
+ * static scopes. Lookups targeting parent static scopes need to be performed
+ * with an absolute path.
+ * <p>
+ * Absolute path lookups use the full path including the dynamic scope followed
+ * by a . and then the static scope. Therefore, variants (or sequences) in lower
+ * levels in the dynamic scope (e.g., event context) can refer to a tag (or
+ * length) field located in upper levels (e.g., in the event header) by
+ * specifying, in this case, the associated tag with
+ * <stream.event.header.field_name>. This allows, for instance, the event
+ * context to define a variant referring to the id field of the event header as
+ * selector.
+ * <p>
+ * The dynamic scope prefixes are thus:
+ * <ul>
+ * <li>Trace environment: <env. ></li>
+ * <li>Trace packet header: <trace.packet.header. ></li>
+ * <li>Stream packet context: <stream.packet.context. ></li>
+ * <li>Event header: <stream.event.header. ></li>
+ * <li>Stream event context: <stream.event.context. ></li>
+ * <li>Event context: <event.context. ></li>
+ * <li>Event payload: <event.fields. ></li>
+ * </ul>
+ * <p>
+ * The target dynamic scope must be specified explicitly when referring to a
+ * field outside of the static scope (absolute scope reference). No conflict can
+ * occur between relative and dynamic paths, because the keywords trace, stream,
+ * and event are reserved, and thus not permitted as field names. It is
+ * recommended that field names clashing with CTF and C99 reserved keywords use
+ * an underscore prefix to eliminate the risk of generating a description
+ * containing an invalid field name. Consequently, fields starting with an
+ * underscore should have their leading underscore removed by the CTF trace
+ * readers.
+ * <p>
+ * The information available in the dynamic scopes can be thought of as the
+ * current tracing context. At trace production, information about the current
+ * context is saved into the specified scope field levels. At trace consumption,
+ * for each event, the current trace context is therefore readable by accessing
+ * the upper dynamic scopes.
+ *
+ * @author Matthew Khouzam - Initial API and implementation
+ * @author Efficios - Description
+ *
+ */
+public final class EventScopeParser implements ICommonTreeParser {
+
+    /**
+     * Parameter object containing a list of common trees
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+        private final List<CommonTree> fList;
+
+        /**
+         * Constructor
+         *
+         * @param list
+         *            parameter list
+         */
+        public Param(List<CommonTree> list) {
+            fList = list;
+
+        }
+
+    }
+
+    /**
+     * Instance
+     */
+    public static final EventScopeParser INSTANCE = new EventScopeParser();
+
+    private EventScopeParser() {
+    }
+
+    /**
+     * Parses in a different way, the AST node is unused, and the event list
+     * contains data to read. This converts a scope from a set of strings to
+     * "event.subscope1.subscope2".
+     *
+     * @param unused
+     *            unused AST node
+     * @param param
+     *            a list of tree nodes that contain the scope description.
+     * @return a concatenated string of the scope
+     */
+    @Override
+    public String parse(CommonTree unused, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        List<CommonTree> lengthChildren = ((Param) param).fList;
+        CommonTree nextElem = (CommonTree) lengthChildren.get(1).getChild(0);
+        String lengthName;
+        switch (nextElem.getType()) {
+        case CTFParser.UNARY_EXPRESSION_STRING:
+        case CTFParser.IDENTIFIER:
+            List<CommonTree> sublist = lengthChildren.subList(1, lengthChildren.size());
+            lengthName = MetadataStrings.EVENT + '.' + concatenateUnaryStrings(sublist);
+            break;
+        default:
+            throw new ParseException("Unsupported scope event." + nextElem); //$NON-NLS-1$
+        }
+        return lengthName;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/floatingpoint/FloatDeclarationParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/floatingpoint/FloatDeclarationParser.java
new file mode 100644 (file)
index 0000000..0650c9c
--- /dev/null
@@ -0,0 +1,180 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.floatingpoint;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.childTypeError;
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.concatenateUnaryStrings;
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isAnyUnaryString;
+
+import java.nio.ByteOrder;
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.core.event.types.FloatDeclaration;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.AlignmentParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.ByteOrderParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.UnaryIntegerParser;
+
+/**
+ *
+ * The floating point values byte ordering is defined in the TSDL metadata.
+ * <p>
+ * Floating point values follow the IEEE 754-2008 standard interchange formats.
+ * Description of the floating point values include the exponent and mantissa
+ * size in bits. Some requirements are imposed on the floating point values:
+ * <ul>
+ * <li>FLT_RADIX must be 2.</li>
+ * <li>mant_dig is the number of digits represented in the mantissa. It is
+ * specified by the ISO C99 standard, section 5.2.4, as FLT_MANT_DIG,
+ * DBL_MANT_DIG and LDBL_MANT_DIG as defined by <float.h>.</li>
+ * <li>exp_dig is the number of digits represented in the exponent. Given that
+ * mant_dig is one bit more than its actual size in bits (leading 1 is not
+ * needed) and also given that the sign bit always takes one bit, exp_dig can be
+ * specified as:</li>
+ * <ul>
+ * <li>sizeof(float) * CHAR_BIT - FLT_MANT_DIG</li>
+ * <li>sizeof(double) * CHAR_BIT - DBL_MANT_DIG</li>
+ * <li>sizeof(long double) * CHAR_BIT - LDBL_MANT_DIG</li>
+ * <li>
+ * </ul>
+ * </ul>
+ *
+ * @author Matthew Khouzam - initial API and implementation
+ * @auttor Efficios - Description
+ *
+ */
+public class FloatDeclarationParser implements ICommonTreeParser {
+
+    private static final String FLOAT_UNKNOWN_ATTRIBUTE = "Float: unknown attribute "; //$NON-NLS-1$
+    private static final String FLOAT_MISSING_SIZE_ATTRIBUTE = "Float: missing size attribute"; //$NON-NLS-1$
+    private static final String IDENTIFIER_MUST_BE_A_STRING = "Left side of ctf expression must be a string"; //$NON-NLS-1$
+
+    /**
+     * Parameter object with only a trace in it
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+        private final CTFTrace fTrace;
+
+        /**
+         * Constructor
+         *
+         * @param trace
+         *            the trace
+         */
+        public Param(CTFTrace trace) {
+            fTrace = trace;
+        }
+    }
+
+    /**
+     * Instance
+     */
+    public static final FloatDeclarationParser INSTANCE = new FloatDeclarationParser();
+
+    private static final int DEFAULT_FLOAT_EXPONENT = 8;
+    private static final int DEFAULT_FLOAT_MANTISSA = 24;
+
+    private FloatDeclarationParser() {
+    }
+
+    /**
+     * Parses a float node and returns a floating point declaration of the
+     * type @link {@link FloatDeclaration}.
+     *
+     * @param floatingPoint
+     *            AST node of type FLOAT
+     * @param param
+     *            parameter containing the trace
+     * @return the float declaration
+     * @throws ParseException
+     *             if a float AST is malformed
+     */
+    @Override
+    public FloatDeclaration parse(CommonTree floatingPoint, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        CTFTrace trace = ((Param) param).fTrace;
+        List<CommonTree> children = floatingPoint.getChildren();
+
+        /*
+         * If the integer has no attributes, then it is missing the size
+         * attribute which is required
+         */
+        if (children == null) {
+            throw new ParseException(FLOAT_MISSING_SIZE_ATTRIBUTE);
+        }
+
+        /* The return value */
+        ByteOrder byteOrder = trace.getByteOrder();
+        long alignment = 0;
+
+        int exponent = DEFAULT_FLOAT_EXPONENT;
+        int mantissa = DEFAULT_FLOAT_MANTISSA;
+
+        /* Iterate on all integer children */
+        for (CommonTree child : children) {
+            switch (child.getType()) {
+            case CTFParser.CTF_EXPRESSION_VAL:
+                /*
+                 * An assignment expression must have 2 children, left and right
+                 */
+
+                CommonTree leftNode = (CommonTree) child.getChild(0);
+                CommonTree rightNode = (CommonTree) child.getChild(1);
+
+                List<CommonTree> leftStrings = leftNode.getChildren();
+
+                if (!isAnyUnaryString(leftStrings.get(0))) {
+                    throw new ParseException(IDENTIFIER_MUST_BE_A_STRING);
+                }
+                String left = concatenateUnaryStrings(leftStrings);
+
+                if (left.equals(MetadataStrings.EXP_DIG)) {
+                    exponent = UnaryIntegerParser.INSTANCE.parse((CommonTree) rightNode.getChild(0), null).intValue();
+                } else if (left.equals(MetadataStrings.BYTE_ORDER)) {
+                    byteOrder = ByteOrderParser.INSTANCE.parse(rightNode, new ByteOrderParser.Param(trace));
+                } else if (left.equals(MetadataStrings.MANT_DIG)) {
+                    mantissa = UnaryIntegerParser.INSTANCE.parse((CommonTree) rightNode.getChild(0), null).intValue();
+                } else if (left.equals(MetadataStrings.ALIGN)) {
+                    alignment = AlignmentParser.INSTANCE.parse(rightNode, null);
+                } else {
+                    throw new ParseException(FLOAT_UNKNOWN_ATTRIBUTE + left);
+                }
+
+                break;
+            default:
+                throw childTypeError(child);
+            }
+        }
+        int size = mantissa + exponent;
+        if (size == 0) {
+            throw new ParseException(FLOAT_MISSING_SIZE_ATTRIBUTE);
+        }
+
+        if (alignment == 0) {
+            alignment = 1;
+        }
+
+        return new FloatDeclaration(exponent, mantissa, byteOrder, alignment);
+
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/integer/BaseParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/integer/BaseParser.java
new file mode 100644 (file)
index 0000000..44fa1bc
--- /dev/null
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.integer;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.concatenateUnaryStrings;
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isUnaryInteger;
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isUnaryString;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.UnaryIntegerParser;
+
+/**
+ * Parse the base of an integer, can return 16, 10, 8 or 2
+ *
+ * @author Matthew Khouzam
+ */
+public final class BaseParser implements ICommonTreeParser {
+
+    /**
+     * BaseParser instance
+     */
+    public static final BaseParser INSTANCE = new BaseParser();
+
+    private static final String INVALID_VALUE_FOR_BASE = "Invalid value for base"; //$NON-NLS-1$
+    private static final int INTEGER_BASE_16 = 16;
+    private static final int INTEGER_BASE_10 = 10;
+    private static final int INTEGER_BASE_8 = 8;
+    private static final int INTEGER_BASE_2 = 2;
+
+    private BaseParser() { }
+
+    @Override
+    public Integer parse(CommonTree tree, ICommonTreeParserParameter param) throws ParseException {
+
+        CommonTree firstChild = (CommonTree) tree.getChild(0);
+
+        if (isUnaryInteger(firstChild)) {
+            if (tree.getChildCount() > 1) {
+                throw new ParseException("invalid base value"); //$NON-NLS-1$
+            }
+
+            long intval = UnaryIntegerParser.INSTANCE.parse(firstChild, null);
+            if ((intval == INTEGER_BASE_2) || (intval == INTEGER_BASE_8) || (intval == INTEGER_BASE_10)
+                    || (intval == INTEGER_BASE_16)) {
+                return (int) intval;
+            }
+            throw new ParseException(INVALID_VALUE_FOR_BASE);
+        } else if (isUnaryString(firstChild)) {
+            switch (concatenateUnaryStrings(tree.getChildren())) {
+            case MetadataStrings.DECIMAL:
+            case MetadataStrings.DEC:
+            case MetadataStrings.DEC_CTE:
+            case MetadataStrings.INT_MOD:
+            case MetadataStrings.UNSIGNED_CTE:
+                return INTEGER_BASE_10;
+            case MetadataStrings.HEXADECIMAL:
+            case MetadataStrings.HEX:
+            case MetadataStrings.X:
+            case MetadataStrings.X2:
+            case MetadataStrings.POINTER:
+                return INTEGER_BASE_16;
+            case MetadataStrings.OCT:
+            case MetadataStrings.OCTAL:
+            case MetadataStrings.OCTAL_CTE:
+                return INTEGER_BASE_8;
+            case MetadataStrings.BIN:
+            case MetadataStrings.BINARY:
+                return INTEGER_BASE_2;
+            default:
+                throw new ParseException(INVALID_VALUE_FOR_BASE);
+            }
+        } else {
+            throw new ParseException(INVALID_VALUE_FOR_BASE);
+        }
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/integer/ClockMapParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/integer/ClockMapParser.java
new file mode 100644 (file)
index 0000000..87d3fea
--- /dev/null
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.integer;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+
+/**
+ * A reference to the clock map in a given integer.
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public class ClockMapParser implements ICommonTreeParser {
+
+    private static final @NonNull String EMPTY_STRING = ""; //$NON-NLS-1$
+
+    /**
+     * Instance
+     */
+    public static final ClockMapParser INSTANCE = new ClockMapParser();
+
+    private ClockMapParser() {
+    }
+
+    @Override
+    public String parse(CommonTree tree, ICommonTreeParserParameter param) {
+        String clock = tree.getChild(1).getChild(0).getChild(0).getText();
+        return clock == null ? EMPTY_STRING : clock;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/integer/IntegerDeclarationParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/integer/IntegerDeclarationParser.java
new file mode 100644 (file)
index 0000000..cc78c66
--- /dev/null
@@ -0,0 +1,208 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.integer;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.childTypeError;
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.concatenateUnaryStrings;
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isAnyUnaryString;
+
+import java.nio.ByteOrder;
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.core.event.types.Encoding;
+import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.Activator;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.Messages;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.AlignmentParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.ByteOrderParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.SizeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.string.EncodingParser;
+
+/**
+ * Signed integers are represented in two-complement. Integer alignment, size,
+ * signedness and byte ordering are defined in the TSDL metadata. Integers
+ * aligned on byte size (8-bit) and with length multiple of byte size (8-bit)
+ * correspond to the C99 standard integers. In addition, integers with alignment
+ * and/or size that are not a multiple of the byte size are permitted; these
+ * correspond to the C99 standard bitfields, with the added specification that
+ * the CTF integer bitfields have a fixed binary representation. Integer size
+ * needs to be a positive integer. Integers of size 0 are forbidden. An
+ * MIT-licensed reference implementation of the CTF portable bitfields is
+ * available here.
+ *
+ * Binary representation of integers:
+ * <ul>
+ * <li>On little and big endian: Within a byte, high bits correspond to an
+ * integer high bits, and low bits correspond to low bits</li>
+ * <li>On little endian: Integer across multiple bytes are placed from the less
+ * significant to the most significant Consecutive integers are placed from
+ * lower bits to higher bits (even within a byte)</li>
+ * <li>On big endian: Integer across multiple bytes are placed from the most
+ * significant to the less significant Consecutive integers are placed from
+ * higher bits to lower bits (even within a byte)</li>
+ * </ul>
+ *
+ * This binary representation is derived from the bitfield implementation in GCC
+ * for little and big endian. However, contrary to what GCC does, integers can
+ * cross units boundaries (no padding is required). Padding can be explicitly
+ * added to follow the GCC layout if needed.
+ *
+ * @author Matthew Khouzam
+ * @author Efficios - javadoc preamble
+ *
+ */
+public class IntegerDeclarationParser implements ICommonTreeParser {
+
+    /**
+     * Parameter Object with a trace
+     *
+     * @author Matthew Khouzam
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+        private final CTFTrace fTrace;
+
+        /**
+         * Constructor
+         *
+         * @param trace
+         *            the trace
+         */
+        public Param(CTFTrace trace) {
+            fTrace = trace;
+        }
+    }
+
+    /**
+     * Instance
+     */
+    public static final IntegerDeclarationParser INSTANCE = new IntegerDeclarationParser();
+
+    private static final @NonNull String ENCODING = "encoding"; //$NON-NLS-1$
+    private static final @NonNull String EMPTY_STRING = ""; //$NON-NLS-1$
+    private static final int DEFAULT_INT_BASE = 10;
+    private static final @NonNull String MAP = "map"; //$NON-NLS-1$
+    private static final @NonNull String BASE = "base"; //$NON-NLS-1$
+    private static final @NonNull String SIZE = "size"; //$NON-NLS-1$
+    private static final @NonNull String SIGNED = "signed"; //$NON-NLS-1$
+
+    private IntegerDeclarationParser() {
+    }
+
+    /**
+     * Parses an integer declaration node.
+     *
+     * @param parameter
+     *            parent trace, for byte orders
+     *
+     * @return The corresponding integer declaration.
+     */
+    @Override
+    public IntegerDeclaration parse(CommonTree integer, ICommonTreeParserParameter parameter) throws ParseException {
+        if (!(parameter instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        CTFTrace trace = ((Param) parameter).fTrace;
+        List<CommonTree> children = integer.getChildren();
+
+        /*
+         * If the integer has no attributes, then it is missing the size
+         * attribute which is required
+         */
+        if (children == null) {
+            throw new ParseException("integer: missing size attribute"); //$NON-NLS-1$
+        }
+
+        /* The return value */
+        IntegerDeclaration integerDeclaration = null;
+        boolean signed = false;
+        ByteOrder byteOrder = trace.getByteOrder();
+        long size = 0;
+        long alignment = 0;
+        int base = DEFAULT_INT_BASE;
+        @NonNull
+        String clock = EMPTY_STRING;
+
+        Encoding encoding = Encoding.NONE;
+
+        /* Iterate on all integer children */
+        for (CommonTree child : children) {
+            switch (child.getType()) {
+            case CTFParser.CTF_EXPRESSION_VAL:
+                /*
+                 * An assignment expression must have 2 children, left and right
+                 */
+
+                CommonTree leftNode = (CommonTree) child.getChild(0);
+                CommonTree rightNode = (CommonTree) child.getChild(1);
+
+                List<CommonTree> leftStrings = leftNode.getChildren();
+
+                if (!isAnyUnaryString(leftStrings.get(0))) {
+                    throw new ParseException("Left side of ctf expression must be a string"); //$NON-NLS-1$
+                }
+                String left = concatenateUnaryStrings(leftStrings);
+
+                switch (left) {
+                case SIGNED:
+                    signed = SignedParser.INSTANCE.parse(rightNode, null);
+                    break;
+                case MetadataStrings.BYTE_ORDER:
+                    byteOrder = ByteOrderParser.INSTANCE.parse(rightNode, new ByteOrderParser.Param(trace));
+                    break;
+                case SIZE:
+                    size = SizeParser.INSTANCE.parse(rightNode, null);
+                    break;
+                case MetadataStrings.ALIGN:
+                    alignment = AlignmentParser.INSTANCE.parse(rightNode, null);
+                    break;
+                case BASE:
+                    base = BaseParser.INSTANCE.parse(rightNode, null);
+                    break;
+                case ENCODING:
+                    encoding = EncodingParser.INSTANCE.parse(rightNode, null);
+                    break;
+                case MAP:
+                    clock = ClockMapParser.INSTANCE.parse(rightNode, null);
+                    break;
+                default:
+                    Activator.log(IStatus.WARNING, Messages.IOStructGen_UnknownIntegerAttributeWarning + " " + left); //$NON-NLS-1$
+                    break;
+                }
+
+                break;
+            default:
+                throw childTypeError(child);
+            }
+        }
+
+        if (size <= 0) {
+            throw new ParseException("Invalid size attribute in Integer: " + size); //$NON-NLS-1$
+        }
+
+        if (alignment == 0) {
+            alignment = 1;
+        }
+
+        integerDeclaration = IntegerDeclaration.createDeclaration((int) size, signed, base,
+                byteOrder, encoding, clock, alignment);
+
+        return integerDeclaration;
+    }
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/integer/SignedParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/integer/SignedParser.java
new file mode 100644 (file)
index 0000000..973b770
--- /dev/null
@@ -0,0 +1,92 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.integer;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.concatenateUnaryStrings;
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isUnaryInteger;
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isUnaryString;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.UnaryIntegerParser;
+
+/**
+ * Singed status, whether an integer is capable of accepting negative values or
+ * not.
+ *
+ * @author Matthew Khouzam
+ */
+public class SignedParser implements ICommonTreeParser {
+    /**
+     * Instance
+     */
+    public static final SignedParser INSTANCE = new SignedParser();
+
+    private static final String INVALID_BOOLEAN_VALUE = "Invalid boolean value "; //$NON-NLS-1$
+
+    private SignedParser() {
+    }
+
+    /**
+     * Parses whether the parent is signed or not. Typical syntax would be
+     * "signed = true;" or "signed = false;"
+     *
+     * @param tree
+     *            the AST node containing "signed = boolean;"
+     * @param unused
+     *            unused
+     * @return @link {@link Boolean#TRUE} if signed, {@link Boolean#FALSE} if
+     *         unsigned
+     * @throws ParseException
+     *             on a malformed tree
+     */
+    @Override
+    public Boolean parse(CommonTree tree, ICommonTreeParserParameter unused) throws ParseException {
+        boolean ret = false;
+        CommonTree firstChild = (CommonTree) tree.getChild(0);
+
+        if (isUnaryString(firstChild)) {
+            String strval = concatenateUnaryStrings(tree.getChildren());
+
+            if (strval.equals(MetadataStrings.TRUE)
+                    || strval.equals(MetadataStrings.TRUE2)) {
+                ret = true;
+            } else if (strval.equals(MetadataStrings.FALSE)
+                    || strval.equals(MetadataStrings.FALSE2)) {
+                ret = false;
+            } else {
+                throw new ParseException(INVALID_BOOLEAN_VALUE
+                        + firstChild.getChild(0).getText());
+            }
+        } else if (isUnaryInteger(firstChild)) {
+            /* Happens if the value is something like "1234.hello" */
+            if (tree.getChildCount() > 1) {
+                throw new ParseException(INVALID_BOOLEAN_VALUE);
+            }
+
+            long intval = UnaryIntegerParser.INSTANCE.parse(firstChild, null);
+
+            if (intval == 1) {
+                ret = true;
+            } else if (intval == 0) {
+                ret = false;
+            } else {
+                throw new ParseException(INVALID_BOOLEAN_VALUE
+                        + firstChild.getChild(0).getText());
+            }
+        } else {
+            throw new ParseException(INVALID_BOOLEAN_VALUE);
+        }
+        return ret;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/stream/StreamDeclarationParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/stream/StreamDeclarationParser.java
new file mode 100644 (file)
index 0000000..75d2609
--- /dev/null
@@ -0,0 +1,257 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.stream;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.concatenateUnaryStrings;
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isAnyUnaryString;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.antlr.runtime.tree.Tree;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.core.CTFStrings;
+import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.IEventHeaderDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.Activator;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.Messages;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TypeSpecifierListParser;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
+
+/**
+ *
+ * An <em>event stream</em> can be divided into contiguous event packets of
+ * variable size. An event packet can contain a certain amount of padding at the
+ * end. The stream header is repeated at the beginning of each event packet.
+ * <br>
+ * The event stream header will therefore be referred to as the
+ * <em>event packet header</em> throughout the rest of this document. <br>
+ *
+ * An event stream is divided in contiguous event packets of variable size.
+ * These subdivisions allow the trace analyzer to perform a fast binary search
+ * by time within the stream (typically requiring to index only the event packet
+ * headers) without reading the whole stream. These subdivisions have a variable
+ * size to eliminate the need to transfer the event packet padding when
+ * partially filled event packets must be sent when streaming a trace for live
+ * viewing/analysis. An event packet can contain a certain amount of padding at
+ * the end. Dividing streams into event packets is also useful for network
+ * streaming over UDP and flight recorder mode tracing (a whole event packet can
+ * be swapped out of the buffer atomically for reading). <br>
+ * The stream header is repeated at the beginning of each event packet to allow
+ * flexibility in terms of:
+ * <ul>
+ * <li>streaming support</li>
+ * <li>allowing arbitrary buffers to be discarded without making the trace
+ * unreadable</li>
+ * <li>allow UDP packet loss handling by either dealing with missing event
+ * packet or asking for re-transmission</li>
+ * <li>transparently support flight recorder mode</li>
+ * <li>transparently support crash dump</li>
+ * </ul>
+ *
+ * @author Matthew Khouzam
+ * @author Efficios - Description
+ *
+ */
+public final class StreamDeclarationParser extends AbstractScopedCommonTreeParser {
+
+    private static final String IDENTIFIER_MUST_BE_A_STRING = "Left side of CTF assignment must be a string"; //$NON-NLS-1$
+    private static final String PACKET_CONTEXT = "packet.context "; //$NON-NLS-1$
+    private static final String EVENT_CONTEXT = "event.context "; //$NON-NLS-1$
+    private static final String EVENT_HEADER = "event.header "; //$NON-NLS-1$
+    private static final String STREAM_ID = "stream id "; //$NON-NLS-1$
+    private static final String EXPECTS_A_STRUCT = "expects a struct"; //$NON-NLS-1$
+    private static final String SCOPE_NOT_FOUND = "scope not found"; //$NON-NLS-1$
+    private static final String EXPECTS_A_TYPE_SPECIFIER = "expects a type specifier"; //$NON-NLS-1$
+    private static final String ALREADY_DEFINED = "already defined"; //$NON-NLS-1$
+
+    /**
+     * A parameter object, contains a trace, a stream and a scope
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+        private final CTFStream fStream;
+        private final CTFTrace fTrace;
+        private final DeclarationScope fDeclarationScope;
+
+        /**
+         * The parameter object
+         *
+         * @param trace
+         *            the trace
+         * @param stream
+         *            the stream
+         * @param scope
+         *            the scope
+         */
+        public Param(CTFTrace trace, CTFStream stream, DeclarationScope scope) {
+            fTrace = trace;
+            fStream = stream;
+            fDeclarationScope = scope;
+        }
+
+    }
+
+    /**
+     * Instance
+     */
+    public static final StreamDeclarationParser INSTANCE = new StreamDeclarationParser();
+
+    private StreamDeclarationParser() {
+    }
+
+    /**
+     * Parse a stream declaration.
+     *
+     * @param streamDecl
+     *            the AST node containing the STREAM type
+     * @param param
+     *            The stream to fill, the trace and the current scope
+     * @return the stream declaration
+     * @throws ParseException
+     *             if the stream AST node is malformed
+     */
+    @Override
+    public CTFStream parse(CommonTree streamDecl, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        DeclarationScope scope = (((Param) param).fDeclarationScope);
+        CTFStream stream = ((Param) param).fStream;
+        CTFTrace fTrace = ((Param) param).fTrace;
+
+        /* There should be a left and right */
+
+        CommonTree leftNode = (CommonTree) streamDecl.getChild(0);
+        CommonTree rightNode = (CommonTree) streamDecl.getChild(1);
+
+        List<CommonTree> leftStrings = leftNode.getChildren();
+
+        if (!isAnyUnaryString(leftStrings.get(0))) {
+            throw new ParseException(IDENTIFIER_MUST_BE_A_STRING);
+        }
+
+        String left = concatenateUnaryStrings(leftStrings);
+
+        if (left.equals(MetadataStrings.ID)) {
+            if (stream.isIdSet()) {
+                throw new ParseException(STREAM_ID + ALREADY_DEFINED);
+            }
+
+            long streamID = StreamIdParser.INSTANCE.parse(rightNode, null);
+
+            stream.setId(streamID);
+        } else if (left.equals(MetadataStrings.EVENT_HEADER)) {
+            if (stream.isEventHeaderSet()) {
+                throw new ParseException(EVENT_HEADER + ALREADY_DEFINED);
+            }
+
+            CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
+
+            if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
+                throw new ParseException(EVENT_HEADER + EXPECTS_A_TYPE_SPECIFIER);
+            }
+
+            IDeclaration eventHeaderDecl = TypeSpecifierListParser.INSTANCE.parse(typeSpecifier, new TypeSpecifierListParser.Param(fTrace, null, null, scope));
+            DeclarationScope eventHeaderScope = lookupStructName(typeSpecifier, scope);
+            if (eventHeaderScope == null) {
+                throw new ParseException(EVENT_HEADER + SCOPE_NOT_FOUND);
+            }
+            DeclarationScope eventScope = new DeclarationScope(scope, MetadataStrings.EVENT);
+            eventScope.addChild(eventHeaderScope);
+            eventHeaderScope.setName(CTFStrings.HEADER);
+
+            if (eventHeaderDecl instanceof StructDeclaration) {
+                stream.setEventHeader((StructDeclaration) eventHeaderDecl);
+            } else if (eventHeaderDecl instanceof IEventHeaderDeclaration) {
+                stream.setEventHeader((IEventHeaderDeclaration) eventHeaderDecl);
+            } else {
+                throw new ParseException(EVENT_HEADER + EXPECTS_A_STRUCT);
+            }
+
+        } else if (left.equals(MetadataStrings.EVENT_CONTEXT)) {
+            if (stream.isEventContextSet()) {
+                throw new ParseException(EVENT_CONTEXT + ALREADY_DEFINED);
+            }
+
+            CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
+
+            if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
+                throw new ParseException(EVENT_CONTEXT + EXPECTS_A_TYPE_SPECIFIER);
+            }
+
+            IDeclaration eventContextDecl = TypeSpecifierListParser.INSTANCE.parse(typeSpecifier, new TypeSpecifierListParser.Param(fTrace, null, null, scope));
+
+            if (!(eventContextDecl instanceof StructDeclaration)) {
+                throw new ParseException(EVENT_CONTEXT + EXPECTS_A_STRUCT);
+            }
+
+            stream.setEventContext((StructDeclaration) eventContextDecl);
+        } else if (left.equals(MetadataStrings.PACKET_CONTEXT)) {
+            if (stream.isPacketContextSet()) {
+                throw new ParseException(PACKET_CONTEXT + ALREADY_DEFINED);
+            }
+
+            CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
+
+            if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
+                throw new ParseException(PACKET_CONTEXT + EXPECTS_A_TYPE_SPECIFIER);
+            }
+
+            IDeclaration packetContextDecl = TypeSpecifierListParser.INSTANCE.parse(typeSpecifier, new TypeSpecifierListParser.Param(fTrace, null, null, scope));
+
+            if (!(packetContextDecl instanceof StructDeclaration)) {
+                throw new ParseException(PACKET_CONTEXT + EXPECTS_A_STRUCT);
+            }
+
+            stream.setPacketContext((StructDeclaration) packetContextDecl);
+        } else {
+            Activator.log(IStatus.WARNING, Messages.IOStructGen_UnknownStreamAttributeWarning + ' ' + left);
+        }
+        return stream;
+    }
+
+    private static DeclarationScope lookupStructName(CommonTree typeSpecifier, DeclarationScope scope) {
+        /*
+         * This needs a struct.struct_name.name to work, luckily, that is 99.99%
+         * of traces we receive.
+         */
+        final Tree potentialStruct = typeSpecifier.getChild(0);
+        DeclarationScope eventHeaderScope = null;
+        if (potentialStruct.getType() == (CTFParser.STRUCT)) {
+            final Tree potentialStructName = potentialStruct.getChild(0);
+            if (potentialStructName.getType() == (CTFParser.STRUCT_NAME)) {
+                final String name = potentialStructName.getChild(0).getText();
+                eventHeaderScope = scope.lookupChildRecursive(name);
+            }
+        }
+        /*
+         * If that fails, maybe the struct is anonymous
+         */
+        if (eventHeaderScope == null) {
+            eventHeaderScope = scope.lookupChildRecursive(MetadataStrings.STRUCT);
+        }
+        /*
+         * This can still be null
+         */
+        return eventHeaderScope;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/stream/StreamIdParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/stream/StreamIdParser.java
new file mode 100644 (file)
index 0000000..b10807c
--- /dev/null
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.stream;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isUnaryInteger;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.UnaryIntegerParser;
+
+/**
+ * <strong>Stream ID</strong>, used as reference to stream description in
+ * metadata. This field is optional if there is only one stream description in
+ * the metadata, but becomes required if there are more than one stream in the
+ * TSDL metadata description.
+ *
+ * @author Matthew Khouzam
+ * @author Efficios - Javadoc
+ *
+ */
+public class StreamIdParser implements ICommonTreeParser {
+
+    /** Instance */
+    public static final StreamIdParser INSTANCE = new StreamIdParser();
+
+    private StreamIdParser() {
+    }
+
+    /**
+     * Parses a stream id
+     *
+     * @param tree
+     *            the AST node with "id = N;"
+     * @return the value of the stream as a {@link Long}
+     */
+    @Override
+    public Long parse(CommonTree tree, ICommonTreeParserParameter param) throws ParseException {
+        CommonTree firstChild = (CommonTree) tree.getChild(0);
+        if (isUnaryInteger(firstChild)) {
+            if (tree.getChildCount() > 1) {
+                throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
+            }
+            long intval = UnaryIntegerParser.INSTANCE.parse(firstChild, null);
+            return intval;
+        }
+        throw new ParseException("invalid value for stream id"); //$NON-NLS-1$
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/stream/StreamParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/stream/StreamParser.java
new file mode 100644 (file)
index 0000000..7c2deed
--- /dev/null
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.stream;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.childTypeError;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TypeAliasParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TypedefParser;
+import org.eclipse.tracecompass.internal.ctf.core.trace.CTFStream;
+
+/**
+ * A stream is a collection of packets with events in them. It will contain data
+ * types.
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public class StreamParser extends AbstractScopedCommonTreeParser {
+
+    /**
+     * Parameter Object with a trace and scope
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+
+        private final DeclarationScope fCurrentScope;
+        private final CTFTrace fTrace;
+
+        /**
+         * Constructor
+         *
+         * @param trace
+         *            the trace
+         * @param currentScope
+         *            the scope
+         */
+        public Param(CTFTrace trace, DeclarationScope currentScope) {
+            fTrace = trace;
+            fCurrentScope = currentScope;
+        }
+
+    }
+
+    /**
+     * The instance
+     */
+    public static final StreamParser INSTANCE = new StreamParser();
+
+    private StreamParser() {
+    }
+
+    /**
+     * Parses an stream declaration and returns a stream type
+     *
+     * @param streamNode
+     *            the steam node
+     * @param param
+     *            the parameter object
+     *
+     * @return The corresponding enum declaration.
+     * @throws ParseException
+     *             badly defined stream
+     */
+    @Override
+    public CTFStream parse(CommonTree streamNode, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        Param parameter = (Param) param;
+        CTFTrace trace = ((Param) param).fTrace;
+        CTFStream stream = new CTFStream(trace);
+
+        List<CommonTree> children = streamNode.getChildren();
+        if (children == null) {
+            throw new ParseException("Empty stream block"); //$NON-NLS-1$
+        }
+
+        DeclarationScope scope = new DeclarationScope(parameter.fCurrentScope, MetadataStrings.STREAM);
+
+        for (CommonTree child : children) {
+            switch (child.getType()) {
+            case CTFParser.TYPEALIAS:
+                TypeAliasParser.INSTANCE.parse(child, new TypeAliasParser.Param(trace, scope));
+                break;
+            case CTFParser.TYPEDEF:
+                TypedefParser.INSTANCE.parse(child, new TypedefParser.Param(trace, scope));
+                break;
+            case CTFParser.CTF_EXPRESSION_TYPE:
+            case CTFParser.CTF_EXPRESSION_VAL:
+                StreamDeclarationParser.INSTANCE.parse(child, new StreamDeclarationParser.Param(trace, stream, scope));
+                break;
+            default:
+                throw childTypeError(child);
+            }
+        }
+
+        if (stream.isIdSet() &&
+                (!trace.packetHeaderIsSet() || !trace.getPacketHeader().hasField(MetadataStrings.STREAM_ID))) {
+            throw new ParseException("Stream has an ID, but there is no stream_id field in packet header."); //$NON-NLS-1$
+        }
+
+        trace.addStream(stream);
+
+        return stream;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/stream/StreamScopeParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/stream/StreamScopeParser.java
new file mode 100644 (file)
index 0000000..4d5b80a
--- /dev/null
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.stream;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.concatenateUnaryStrings;
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isUnaryString;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.UnaryStringParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.event.EventScopeParser;
+
+/**
+ * The stream scope parser, this parses a scope of a given stream. It can get
+ * the scope of the stream like "stream.packet.header".
+ *
+ * @author Matthew Khouzam - Initial API and implementation
+ *
+ */
+public final class StreamScopeParser implements ICommonTreeParser {
+
+    /**
+     * Parameter object
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+        private final List<CommonTree> fList;
+
+        /**
+         * Constructor
+         *
+         * @param list
+         *            a list of commonTrees to parse
+         */
+        public Param(List<CommonTree> list) {
+            fList = list;
+        }
+
+    }
+
+    /**
+     * Instance
+     */
+    public static final StreamScopeParser INSTANCE = new StreamScopeParser();
+
+    private StreamScopeParser() {
+    }
+
+    /**
+     * Parses the scope of the stream and returns a concatenated string of the
+     * elements
+     *
+     * @param unused
+     *            unused
+     * @param param
+     *            the parameter containing a list of ASTs describing the stream
+     *            scope
+     * @return a string of the scope like "stream.context"
+     * @throws ParseException
+     *             if the ASTs are malformed
+     */
+    @Override
+    public String parse(CommonTree unused, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        List<@NonNull CommonTree> lengthChildren = ((Param) param).fList;
+        final List<@NonNull CommonTree> sublist = lengthChildren.subList(1, lengthChildren.size());
+
+        CommonTree nextElem = (CommonTree) lengthChildren.get(1).getChild(0);
+        String lengthName = null;
+        if (isUnaryString(nextElem)) {
+            lengthName = UnaryStringParser.INSTANCE.parse(nextElem, null);
+        }
+
+        int type = nextElem.getType();
+        if ((CTFParser.tokenNames[CTFParser.EVENT]).equals(lengthName)) {
+            type = CTFParser.EVENT;
+        }
+        switch (type) {
+        case CTFParser.IDENTIFIER:
+            lengthName = concatenateUnaryStrings(sublist);
+            break;
+        case CTFParser.EVENT:
+            lengthName = EventScopeParser.INSTANCE.parse(null, new EventScopeParser.Param(sublist));
+            break;
+        default:
+            if (lengthName == null) {
+                throw new ParseException("Unsupported scope stream." + nextElem); //$NON-NLS-1$
+            }
+        }
+        return MetadataStrings.STREAM + '.' + lengthName;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/string/EncodingParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/string/EncodingParser.java
new file mode 100644 (file)
index 0000000..00e2bd1
--- /dev/null
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.string;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.concatenateUnaryStrings;
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isUnaryString;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.tracecompass.ctf.core.event.types.Encoding;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ * Parse the encoding field. This can be "ascii", "utf8" or "none"
+ *
+ * @author Matthew Khouzam
+ */
+public class EncodingParser implements ICommonTreeParser {
+
+    /**
+     * Instance
+     */
+    public static final EncodingParser INSTANCE = new EncodingParser();
+
+    private EncodingParser() { }
+
+    private static final String INVALID_VALUE_FOR_ENCODING = "Invalid value for encoding"; //$NON-NLS-1$
+
+    /**
+     * Gets the value of an "encoding" integer attribute.
+     *
+     * @return The "encoding" value.
+     * @throws ParseException
+     *             for unknown or malformed encoding
+     */
+    @Override
+    public Encoding parse(CommonTree tree, ICommonTreeParserParameter param) throws ParseException {
+        CommonTree firstChild = (CommonTree) tree.getChild(0);
+
+        if (isUnaryString(firstChild)) {
+            String strval = concatenateUnaryStrings(tree.getChildren());
+
+            if (strval.equals(MetadataStrings.UTF8)) {
+                return Encoding.UTF8;
+            } else if (strval.equals(MetadataStrings.ASCII)) {
+                return Encoding.ASCII;
+            } else if (strval.equals(MetadataStrings.NONE)) {
+                return Encoding.NONE;
+            } else {
+                throw new ParseException(INVALID_VALUE_FOR_ENCODING);
+            }
+        }
+        throw new ParseException(INVALID_VALUE_FOR_ENCODING);
+
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/string/StringDeclarationParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/string/StringDeclarationParser.java
new file mode 100644 (file)
index 0000000..76a5766
--- /dev/null
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.string;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.childTypeError;
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.concatenateUnaryStrings;
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isAnyUnaryString;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.tracecompass.ctf.core.event.types.Encoding;
+import org.eclipse.tracecompass.ctf.core.event.types.StringDeclaration;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ * Strings are an array of bytes of variable size and are terminated by a '\0'
+ * “NULL” character. Their encoding is described in the TSDL metadata. In
+ * absence of encoding attribute information, the default encoding is UTF-8.
+ *
+ * TSDL metadata representation of a named string type:
+ *
+ * <pre>
+ * typealias string {
+ *   encoding = /* UTF8 OR ASCII * /;
+ * } := name;
+ * </pre>
+ *
+ * A nameless string type can be declared as a field type:
+ *
+ * <pre>
+ * string field_name; /* use default UTF8 encoding * /
+ * </pre>
+ *
+ * Strings are always aligned on byte size.
+ *
+ * @author Matthew Khouzam
+ * @author Efficios - Javadoc Preable
+ *
+ */
+public class StringDeclarationParser implements ICommonTreeParser {
+
+    /**
+     * Instance
+     */
+    public static final StringDeclarationParser INSTANCE = new StringDeclarationParser();
+
+    private static final @NonNull String ENCODING = "encoding"; //$NON-NLS-1$
+
+    private StringDeclarationParser() {
+    }
+
+    /**
+     * Parse a string declaration node and return a {@link StringDeclaration}
+     *
+     * @param string
+     *            the string declaration AST node
+     * @param unused
+     *            unused
+     * @return a {@link StringDeclaration} describing the string layout
+     * @throws ParseException
+     *             the AST is malformed
+     */
+    @Override
+    public StringDeclaration parse(CommonTree string, ICommonTreeParserParameter unused) throws ParseException {
+        List<CommonTree> children = string.getChildren();
+        StringDeclaration stringDeclaration = null;
+
+        if (children == null) {
+            stringDeclaration = StringDeclaration.getStringDeclaration(Encoding.UTF8);
+        } else {
+            Encoding encoding = Encoding.UTF8;
+            for (CommonTree child : children) {
+                switch (child.getType()) {
+                case CTFParser.CTF_EXPRESSION_VAL:
+                    /*
+                     * An assignment expression must have 2 children, left and
+                     * right
+                     */
+
+                    CommonTree leftNode = (CommonTree) child.getChild(0);
+                    CommonTree rightNode = (CommonTree) child.getChild(1);
+
+                    List<CommonTree> leftStrings = leftNode.getChildren();
+
+                    if (!isAnyUnaryString(leftStrings.get(0))) {
+                        throw new ParseException("Left side of ctf expression must be a string"); //$NON-NLS-1$
+                    }
+                    String left = concatenateUnaryStrings(leftStrings);
+
+                    if (left.equals(ENCODING)) {
+                        encoding = EncodingParser.INSTANCE.parse(rightNode, null);
+                    } else {
+                        throw new ParseException("String: unknown attribute " //$NON-NLS-1$
+                                + left);
+                    }
+
+                    break;
+                default:
+                    throw childTypeError(child);
+                }
+            }
+
+            stringDeclaration = StringDeclaration.getStringDeclaration(encoding);
+        }
+
+        return stringDeclaration;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/struct/StructBodyParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/struct/StructBodyParser.java
new file mode 100644 (file)
index 0000000..7074de2
--- /dev/null
@@ -0,0 +1,159 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.struct;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.childTypeError;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
+import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TypeAliasParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TypedefParser;
+
+/**
+ * A struct body can have any of the following elements, even though some of
+ * them do not make sense:
+ * <ul>
+ * <li>align</li>
+ * <li>callsite</li>
+ * <li>const</li>
+ * <li>char</li>
+ * <li>clock</li>
+ * <li>double</li>
+ * <li>enum</li>
+ * <li>env</li>
+ * <li>event</li>
+ * <li>floating_point</li>
+ * <li>float</li>
+ * <li>integer</li>
+ * <li>int</li>
+ * <li>long</li>
+ * <li>short</li>
+ * <li>signed</li>
+ * <li>stream</li>
+ * <li>string</li>
+ * <li>struct</li>
+ * <li>trace</li>
+ * <li>typealias</li>
+ * <li>typedef</li>
+ * <li>unsigned</li>
+ * <li>variant</li>
+ * <li>void</li>
+ * <li>_Bool</li>
+ * <li>_Complex</li>
+ * <li>_Imaginary</li>
+ * </ul>
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public class StructBodyParser extends AbstractScopedCommonTreeParser {
+
+    /**
+     * The parameter object
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+        private final DeclarationScope fDeclarationScope;
+        private final @Nullable String fName;
+        private final StructDeclaration fStructDeclaration;
+        private final CTFTrace fTrace;
+
+        /**
+         * Constructor
+         *
+         * @param structDeclaration
+         *            struct declaration to populate
+         * @param trace
+         *            the trace
+         * @param name
+         *            the struct name
+         * @param scope
+         *            the current scope
+         */
+        public Param(StructDeclaration structDeclaration, CTFTrace trace, @Nullable String name, DeclarationScope scope) {
+            fStructDeclaration = structDeclaration;
+            fTrace = trace;
+            fDeclarationScope = scope;
+            fName = name;
+        }
+    }
+
+    /**
+     * The instance
+     */
+    public final static StructBodyParser INSTANCE = new StructBodyParser();
+
+    private StructBodyParser() {
+    }
+
+    /**
+     * Parse the body of a struct, so anything between the '{' '}'
+     *
+     * @param structBody
+     *            the struct body AST node
+     * @param param
+     *            the struct body parameters
+     * @return {@link StructDeclaration} that is now populated
+     * @throws ParseException
+     *             The AST is malformed
+     */
+    @Override
+    public StructDeclaration parse(CommonTree structBody, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        String structName = ((Param) param).fName;
+        final DeclarationScope scope = new DeclarationScope(((Param) param).fDeclarationScope, structName == null ? MetadataStrings.STRUCT : structName);
+        StructDeclaration structDeclaration = ((Param) param).fStructDeclaration;
+        List<CommonTree> structDeclarations = structBody.getChildren();
+        if (structDeclarations == null) {
+            structDeclarations = Collections.emptyList();
+        }
+
+        /*
+         * If structDeclaration is null, structBody has no children and the
+         * struct body is empty.
+         */
+
+        CTFTrace trace = ((Param) param).fTrace;
+
+        for (CommonTree declarationNode : structDeclarations) {
+            switch (declarationNode.getType()) {
+            case CTFParser.TYPEALIAS:
+                TypeAliasParser.INSTANCE.parse(declarationNode, new TypeAliasParser.Param(trace, scope));
+                break;
+            case CTFParser.TYPEDEF:
+                TypedefParser.INSTANCE.parse(declarationNode, new TypedefParser.Param(trace, scope));
+                StructDeclarationParser.INSTANCE.parse(declarationNode, new StructDeclarationParser.Param(structDeclaration, trace, scope));
+                break;
+            case CTFParser.SV_DECLARATION:
+                StructDeclarationParser.INSTANCE.parse(declarationNode, new StructDeclarationParser.Param(structDeclaration, trace, scope));
+                break;
+            default:
+                throw childTypeError(declarationNode);
+            }
+        }
+        return structDeclaration;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/struct/StructDeclarationParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/struct/StructDeclarationParser.java
new file mode 100644 (file)
index 0000000..5579669
--- /dev/null
@@ -0,0 +1,127 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.struct;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TypeDeclaratorParser;
+
+/**
+ * Structures follow the ISO/C standard for structures
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public class StructDeclarationParser extends AbstractScopedCommonTreeParser {
+
+    /**
+     * Parameter object
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+        private final StructDeclaration fStruct;
+        private final DeclarationScope fDeclarationScope;
+        private final CTFTrace fTrace;
+
+        /**
+         * Constructor
+         *
+         * @param struct
+         *            the structure declaration
+         * @param trace
+         *            the trace
+         * @param scope
+         *            the current scope
+         */
+        public Param(StructDeclaration struct, CTFTrace trace, DeclarationScope scope) {
+            fStruct = struct;
+            fTrace = trace;
+            fDeclarationScope = scope;
+        }
+    }
+
+    /**
+     * The instance
+     */
+    public final static StructDeclarationParser INSTANCE = new StructDeclarationParser();
+
+    private StructDeclarationParser() {
+    }
+
+    /**
+     * Parses a declaration found in a struct.
+     *
+     * @param declaration
+     *            A SV_DECLARATION node.
+     * @param param
+     *            The parameter object
+     * @throws ParseException
+     *             for poorly formed structs (duplicate fields, etc...)
+     */
+    @Override
+    public StructDeclaration parse(CommonTree declaration, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        DeclarationScope scope = ((Param) param).fDeclarationScope;
+        StructDeclaration struct = ((Param) param).fStruct;
+        /* Get the type specifier list node */
+        CommonTree typeSpecifierListNode = (CommonTree) declaration.getFirstChildWithType(CTFParser.TYPE_SPECIFIER_LIST);
+
+        if (typeSpecifierListNode == null) {
+            throw new ParseException("Cannot have an struct without a type specifier"); //$NON-NLS-1$
+        }
+
+        /* Get the type declarator list node */
+        CommonTree typeDeclaratorListNode = (CommonTree) declaration.getFirstChildWithType(CTFParser.TYPE_DECLARATOR_LIST);
+
+        if (typeDeclaratorListNode == null) {
+            throw new ParseException("Cannot have an struct without a declarator"); //$NON-NLS-1$
+        }
+
+        /* Get the type declarator list */
+        List<CommonTree> typeDeclaratorList = typeDeclaratorListNode.getChildren();
+
+        /*
+         * For each type declarator, parse the declaration and add a field to
+         * the struct
+         */
+        for (CommonTree typeDeclaratorNode : typeDeclaratorList) {
+
+            StringBuilder identifierSB = new StringBuilder();
+
+            CTFTrace trace = ((Param) param).fTrace;
+            IDeclaration decl = TypeDeclaratorParser.INSTANCE.parse(typeDeclaratorNode, new TypeDeclaratorParser.Param(trace, typeSpecifierListNode, scope, identifierSB));
+            String fieldName = identifierSB.toString();
+            scope.registerIdentifier(fieldName, decl);
+
+            if (struct.hasField(fieldName)) {
+                throw new ParseException("struct: duplicate field " //$NON-NLS-1$
+                        + fieldName);
+            }
+
+            struct.addField(fieldName, decl);
+
+        }
+        return struct;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/struct/StructParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/struct/StructParser.java
new file mode 100644 (file)
index 0000000..37dbb4f
--- /dev/null
@@ -0,0 +1,254 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.struct;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.childTypeError;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
+import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.AlignmentParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.types.StructDeclarationFlattener;
+
+/**
+ *
+ * Structures are aligned on the largest alignment required by basic types
+ * contained within the structure. (This follows the ISO/C standard for
+ * structures) <br>
+ * TSDL metadata representation of a named structure:
+ *
+ * <pre>
+struct name {
+    field_type field_name;
+    field_type field_name;
+    // ...
+};
+ * </pre>
+ *
+ * Example:
+ *
+ * <pre>
+struct example {
+    integer {                   // nameless type
+        size = 16;
+        signed = true;
+        align = 16;
+    } first_field_name;
+    uint64_t second_field_name; // named type declared in the metadata
+};
+ * </pre>
+ *
+ * The fields are placed in a sequence next to each other. They each possess a
+ * field name, which is a unique identifier within the structure. The identifier
+ * is not allowed to use any [reserved keyword](#specC.1.2). Replacing reserved
+ * keywords with underscore-prefixed field names is <strong>recommended</strong>
+ * . Fields starting with an underscore should have their leading underscore
+ * removed by the CTF trace readers. <br>
+ * A nameless structure can be declared as a field type or as part of a
+ * `typedef`:
+ *
+ * <pre>
+struct {
+    // ...
+}
+ *
+ * </pre>
+ *
+ * Alignment for a structure compound type can be forced to a minimum value by
+ * adding an `align` specifier after the declaration of a structure body. This
+ * attribute is read as: `align(value)`. The value is specified in bits. The
+ * structure will be aligned on the maximum value between this attribute and the
+ * alignment required by the basic types contained within the structure. e.g.
+ *
+ * <pre>
+struct {
+    // ...
+} align(32)
+}
+ * </pre>
+ *
+ * @author Matthew Khouzam
+ * @author Efficios - Javadoc preamble
+ */
+public class StructParser extends AbstractScopedCommonTreeParser {
+
+    /**
+     * Parameter object
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+        private final DeclarationScope fDeclarationScope;
+        private final @Nullable CommonTree fIdentifier;
+        private final CTFTrace fTrace;
+
+        /**
+         * Constructor
+         *
+         * @param trace
+         *            the trace
+         * @param identifier
+         *            the identifier
+         * @param scope
+         *            the current scope
+         */
+        public Param(CTFTrace trace, @Nullable CommonTree identifier, DeclarationScope scope) {
+            fTrace = trace;
+            fIdentifier = identifier;
+            fDeclarationScope = scope;
+        }
+    }
+
+    /**
+     * The instance
+     */
+    public final static StructParser INSTANCE = new StructParser();
+
+    private StructParser() {
+    }
+
+    /**
+     * Parse the struct AST node, So everything in "struct a {...};"
+     *
+     * @param struct
+     *            the struct AST node
+     * @param param
+     *            the parameter object of {@link Param} type.
+     * @return a {@link StructDeclaration} that is fully populated
+     * @throws ParseException
+     *             the AST is malformed
+     */
+    @Override
+    public StructDeclaration parse(CommonTree struct, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        final DeclarationScope scope = ((Param) param).fDeclarationScope;
+        CommonTree identifier = ((Param) param).fIdentifier;
+
+        List<CommonTree> children = struct.getChildren();
+
+        /* The return value */
+        StructDeclaration structDeclaration = null;
+
+        /* Name */
+        String structName = null;
+        boolean hasName = false;
+
+        /* Body */
+        CommonTree structBody = null;
+        boolean hasBody = false;
+
+        /* Align */
+        long structAlign = 0;
+
+        /* Loop on all children and identify what we have to work with. */
+        for (CommonTree child : children) {
+            switch (child.getType()) {
+            case CTFParser.STRUCT_NAME: {
+                hasName = true;
+                CommonTree structNameIdentifier = (CommonTree) child.getChild(0);
+                structName = structNameIdentifier.getText();
+                break;
+            }
+            case CTFParser.STRUCT_BODY: {
+                hasBody = true;
+
+                structBody = child;
+                break;
+            }
+            case CTFParser.ALIGN: {
+                CommonTree structAlignExpression = (CommonTree) child.getChild(0);
+
+                structAlign = AlignmentParser.INSTANCE.parse(structAlignExpression, null);
+                break;
+            }
+            default:
+                throw childTypeError(child);
+            }
+        }
+
+        if (!hasName && identifier != null) {
+            structName = identifier.getText();
+            hasName = true;
+        }
+
+        /*
+         * If a struct has just a body and no name (just like the song,
+         * "A Struct With No Name" by America (sorry for that...)), it's a
+         * definition of a new type, so we create the type declaration and
+         * return it. We can't add it to the declaration scope since there is no
+         * name, but that's what we want because it won't be possible to use it
+         * again to declare another field.
+         *
+         * If it has just a name, we look it up in the declaration scope and
+         * return the associated declaration. If it is not found in the
+         * declaration scope, it means that a struct with that name has not been
+         * declared, which is an error.
+         *
+         * If it has both, then we create the type declaration and register it
+         * to the current scope.
+         *
+         * If it has none, then what are we doing here ?
+         */
+        if (hasBody) {
+            /*
+             * If struct has a name, check if already defined in the current
+             * scope.
+             */
+            if (hasName && (scope.lookupStruct(structName) != null)) {
+                throw new ParseException("struct " + structName //$NON-NLS-1$
+                        + " already defined."); //$NON-NLS-1$
+            }
+            /* Create the declaration */
+            structDeclaration = new StructDeclaration(structAlign);
+
+            CTFTrace trace = ((Param) param).fTrace;
+            /* Parse the body */
+            StructBodyParser.INSTANCE.parse(structBody, new StructBodyParser.Param(structDeclaration, trace, structName, scope));
+            /* If struct has name, add it to the current scope. */
+            if (hasName) {
+                scope.registerStruct(structName, structDeclaration);
+            }
+        } else /* !hasBody */ {
+            if (hasName) {
+                /* Name and !body */
+
+                /* Lookup the name in the current scope. */
+                structDeclaration = scope.lookupStructRecursive(structName);
+
+                /*
+                 * If not found, it means that a struct with such name has not
+                 * been defined
+                 */
+                if (structDeclaration == null) {
+                    throw new ParseException("struct " + structName //$NON-NLS-1$
+                            + " is not defined"); //$NON-NLS-1$
+                }
+            } else {
+                /* !Name and !body */
+
+                /* We can't do anything with that. */
+                throw new ParseException("struct with no name and no body"); //$NON-NLS-1$
+            }
+        }
+        return StructDeclarationFlattener.tryFlattenStruct(structDeclaration);
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/trace/TraceDeclarationParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/trace/TraceDeclarationParser.java
new file mode 100644 (file)
index 0000000..3c75cd5
--- /dev/null
@@ -0,0 +1,303 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.trace;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.concatenateUnaryStrings;
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isAnyUnaryString;
+
+import java.nio.ByteOrder;
+import java.util.List;
+import java.util.Map.Entry;
+import java.util.UUID;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
+import org.eclipse.tracecompass.ctf.core.event.types.EnumDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.EnumDeclaration.Pair;
+import org.eclipse.tracecompass.ctf.core.event.types.FloatDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.VariantDeclaration;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.Activator;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.Messages;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.ByteOrderParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TypeSpecifierListParser;
+
+/**
+ *
+ * A <em>trace<em> is divided into multiple event streams. Each event stream
+ * contains a subset of the trace event types. <br>
+ * The final output of the trace, after its generation and optional transport
+ * over the network, is expected to be either on permanent or temporary storage
+ * in a virtual file system. Because each event stream is appended to while a
+ * trace is being recorded, each is associated with a distinct set of files for
+ * output. Therefore, a stored trace can be represented as a directory
+ * containing zero, one or more files per stream. <br>
+ * Metadata description associated with the trace contains information on trace
+ * event types expressed in the _Trace Stream Description Language_ (TSDL). This
+ * language describes: <br>
+ * <ul>
+ * <li>Trace version</li>
+ * <li>Types available</li>
+ * <li>Per-trace event header description</li>
+ * <li>Per-stream event header description</li>
+ * <li>Per-stream event context description</li>
+ * <li>Per-event
+ * <ul>
+ * <li>Event type to stream mapping</li>
+ * <li>Event type to name mapping</li>
+ * <li>Event type to ID mapping</li>
+ * <li>Event context description</li>
+ * <li>Event fields description</li>
+ * </ul>
+ * </ul>
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public class TraceDeclarationParser extends AbstractScopedCommonTreeParser {
+
+    /**
+     * Parameter object
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+
+        private final DeclarationScope fCurrentScope;
+        private final CTFTrace fTrace;
+
+        /**
+         * Parameter Object
+         *
+         * @param trace
+         *            the trace
+         * @param currentScope
+         *            the current scope
+         */
+        public Param(CTFTrace trace, DeclarationScope currentScope) {
+            fTrace = trace;
+            fCurrentScope = currentScope;
+        }
+
+    }
+
+    /**
+     * Parser instance
+     */
+    public static final TraceDeclarationParser INSTANCE = new TraceDeclarationParser();
+
+    private TraceDeclarationParser() {
+    }
+
+    /**
+     * Parse a trace AST node
+     *
+     * @param traceDecl
+     *            trace AST node
+     * @param param
+     *            A parameter object of the type {@link Param}
+     * @return a {@link CTFTrace} that is populated
+     * @throws ParseException
+     *             if the AST is malformed
+     */
+    @Override
+    public CTFTrace parse(CommonTree traceDecl, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        CTFTrace trace = ((Param) param).fTrace;
+        DeclarationScope scope = ((Param) param).fCurrentScope;
+
+        /* There should be a left and right */
+        CommonTree leftNode = (CommonTree) traceDecl.getChild(0);
+        CommonTree rightNode = (CommonTree) traceDecl.getChild(1);
+
+        List<CommonTree> leftStrings = leftNode.getChildren();
+
+        if (!isAnyUnaryString(leftStrings.get(0))) {
+            throw new ParseException("Left side of CTF assignment must be a string"); //$NON-NLS-1$
+        }
+
+        String left = concatenateUnaryStrings(leftStrings);
+
+        if (left.equals(MetadataStrings.MAJOR)) {
+            if (trace.majorIsSet()) {
+                throw new ParseException("major is already set"); //$NON-NLS-1$
+            }
+
+            trace.setMajor(VersionNumberParser.INSTANCE.parse(rightNode, null));
+        } else if (left.equals(MetadataStrings.MINOR)) {
+            if (trace.minorIsSet()) {
+                throw new ParseException("minor is already set"); //$NON-NLS-1$
+            }
+
+            trace.setMinor(VersionNumberParser.INSTANCE.parse(rightNode, null));
+        } else if (left.equals(MetadataStrings.UUID_STRING)) {
+            UUID uuid = UUIDParser.INSTANCE.parse(rightNode, null);
+
+            /*
+             * If uuid was already set by a metadata packet, compare it to see
+             * if it matches
+             */
+            if (trace.uuidIsSet()) {
+                if (trace.getUUID().compareTo(uuid) != 0) {
+                    throw new ParseException("UUID mismatch. Packet says " //$NON-NLS-1$
+                            + trace.getUUID() + " but metadata says " + uuid); //$NON-NLS-1$
+                }
+            } else {
+                trace.setUUID(uuid);
+            }
+
+        } else if (left.equals(MetadataStrings.BYTE_ORDER)) {
+            ByteOrder byteOrder = ByteOrderParser.INSTANCE.parse(rightNode, new ByteOrderParser.Param(trace));
+
+            /*
+             * If byte order was already set by a metadata packet, compare it to
+             * see if it matches
+             */
+            if (trace.getByteOrder() != null) {
+                if (trace.getByteOrder() != byteOrder) {
+                    throw new ParseException(
+                            "Endianness mismatch. Magic number says " //$NON-NLS-1$
+                                    + trace.getByteOrder()
+                                    + " but metadata says " + byteOrder); //$NON-NLS-1$
+                }
+            } else {
+                trace.setByteOrder(byteOrder);
+
+                final DeclarationScope currentScope = scope;
+                for (String type : currentScope.getTypeNames()) {
+                    IDeclaration d = currentScope.lookupType(type);
+                    if (d instanceof IntegerDeclaration) {
+                        addByteOrder(byteOrder, currentScope, type, (IntegerDeclaration) d);
+                    } else if (d instanceof FloatDeclaration) {
+                        addByteOrder(byteOrder, currentScope, type, (FloatDeclaration) d);
+                    } else if (d instanceof EnumDeclaration) {
+                        addByteOrder(byteOrder, currentScope, type, (EnumDeclaration) d);
+                    } else if (d instanceof StructDeclaration) {
+                        setAlign(currentScope, (StructDeclaration) d, byteOrder);
+                    }
+                }
+            }
+        } else if (left.equals(MetadataStrings.PACKET_HEADER)) {
+            if (trace.packetHeaderIsSet()) {
+                throw new ParseException("packet.header already defined"); //$NON-NLS-1$
+            }
+
+            CommonTree typeSpecifier = (CommonTree) rightNode.getChild(0);
+
+            if (typeSpecifier.getType() != CTFParser.TYPE_SPECIFIER_LIST) {
+                throw new ParseException("packet.header expects a type specifier"); //$NON-NLS-1$
+            }
+
+            IDeclaration packetHeaderDecl = TypeSpecifierListParser.INSTANCE.parse(typeSpecifier, new TypeSpecifierListParser.Param(trace, null, null, scope));
+
+            if (!(packetHeaderDecl instanceof StructDeclaration)) {
+                throw new ParseException("packet.header expects a struct"); //$NON-NLS-1$
+            }
+
+            trace.setPacketHeader((StructDeclaration) packetHeaderDecl);
+        } else {
+            Activator.log(IStatus.WARNING, Messages.IOStructGen_UnknownTraceAttributeWarning + " " + left); //$NON-NLS-1$
+        }
+        return trace;
+    }
+
+    private static void addByteOrder(ByteOrder byteOrder,
+            final DeclarationScope parentScope, String name,
+            IntegerDeclaration decl) throws ParseException {
+
+        if (!decl.isByteOrderSet()) {
+            IntegerDeclaration newI;
+            newI = IntegerDeclaration.createDeclaration(decl.getLength(), decl.isSigned(),
+                    decl.getBase(), byteOrder, decl.getEncoding(),
+                    decl.getClock(), decl.getAlignment());
+            parentScope.replaceType(name, newI);
+        }
+    }
+
+    private static void addByteOrder(ByteOrder byteOrder, DeclarationScope parentScope, String name, EnumDeclaration decl) throws ParseException {
+        if (!decl.isByteOrderSet()) {
+            final IntegerDeclaration containerType = decl.getContainerType();
+            EnumDeclaration newEnum = new EnumDeclaration(IntegerDeclaration.createDeclaration(containerType.getLength(), containerType.isSigned(),
+                    containerType.getBase(), byteOrder, containerType.getEncoding(),
+                    containerType.getClock(), containerType.getAlignment()));
+            for (Entry<String, Pair> entry : decl.getEnumTable().entrySet()) {
+                newEnum.add(entry.getValue().getFirst(), entry.getValue().getSecond(), entry.getKey());
+            }
+
+            parentScope.replaceType(name, newEnum);
+        }
+    }
+
+    private static void addByteOrder(ByteOrder byteOrder, DeclarationScope parentScope, String name, FloatDeclaration decl) throws ParseException {
+        if (!decl.isByteOrderSet()) {
+            FloatDeclaration newFloat = new FloatDeclaration(decl.getExponent(), decl.getMantissa(), byteOrder, decl.getAlignment());
+            parentScope.replaceType(name, newFloat);
+        }
+    }
+
+    private void setAlign(DeclarationScope parentScope, StructDeclaration sd,
+            ByteOrder byteOrder) throws ParseException {
+
+        for (String s : sd.getFieldsList()) {
+            IDeclaration d = sd.getField(s);
+
+            if (d instanceof StructDeclaration) {
+                setAlign(parentScope, (StructDeclaration) d, byteOrder);
+
+            } else if (d instanceof VariantDeclaration) {
+                setAlign(parentScope, (VariantDeclaration) d, byteOrder);
+            } else if (d instanceof IntegerDeclaration) {
+                IntegerDeclaration decl = (IntegerDeclaration) d;
+                if (decl.getByteOrder() != byteOrder) {
+                    IntegerDeclaration newI;
+                    newI = IntegerDeclaration.createDeclaration(decl.getLength(),
+                            decl.isSigned(), decl.getBase(), byteOrder,
+                            decl.getEncoding(), decl.getClock(),
+                            decl.getAlignment());
+                    sd.getFields().put(s, newI);
+                }
+            }
+        }
+    }
+
+    private void setAlign(DeclarationScope parentScope, VariantDeclaration vd,
+            ByteOrder byteOrder) throws ParseException {
+
+        for (String s : vd.getFields().keySet()) {
+            IDeclaration d = vd.getFields().get(s);
+
+            if (d instanceof StructDeclaration) {
+                setAlign(parentScope, (StructDeclaration) d, byteOrder);
+
+            } else if (d instanceof IntegerDeclaration) {
+                IntegerDeclaration decl = (IntegerDeclaration) d;
+                IntegerDeclaration newI;
+                newI = IntegerDeclaration.createDeclaration(decl.getLength(),
+                        decl.isSigned(), decl.getBase(), byteOrder,
+                        decl.getEncoding(), decl.getClock(),
+                        decl.getAlignment());
+                vd.getFields().put(s, newI);
+            }
+        }
+    }
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/trace/TraceScopeParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/trace/TraceScopeParser.java
new file mode 100644 (file)
index 0000000..5e2784d
--- /dev/null
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.trace;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.concatenateUnaryStrings;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNull;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.stream.StreamScopeParser;
+
+/**
+ * TSDL uses three different types of scoping: a lexical scope is used for
+ * declarations and type definitions, and static and dynamic scopes are used for
+ * variants references to tag fields (with relative and absolute path lookups)
+ * and for sequence references to length fields.
+ *
+ * @author Matthew Khouzam
+ * @author Efficios - Description
+ *
+ */
+public final class TraceScopeParser implements ICommonTreeParser {
+
+    /**
+     * Parameter object
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+        private final List<CommonTree> fList;
+
+        /**
+         * Parameter object constructor
+         *
+         * @param list
+         *            the list of subtrees
+         */
+        public Param(List<CommonTree> list) {
+            fList = list;
+
+        }
+
+    }
+
+    /**
+     * Instance
+     */
+    public static final TraceScopeParser INSTANCE = new TraceScopeParser();
+
+    private TraceScopeParser() {
+    }
+
+    /**
+     * Parse a trace scope to get a concatenated scope name. Like
+     * "trace.version.minor"
+     *
+     * @param unused
+     *            unused
+     * @param param
+     *            a {@link Param} containing the list of ASTs to make the scope
+     * @return a {@link String} of the scope
+     * @throws ParseException
+     *             an AST was malformed
+     *
+     */
+    @Override
+    public String parse(CommonTree unused, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        List<@NonNull CommonTree> lengthChildren = ((Param) param).fList;
+        CommonTree nextElem = (CommonTree) lengthChildren.get(1).getChild(0);
+        switch (nextElem.getType()) {
+        case CTFParser.IDENTIFIER:
+            return concatenateUnaryStrings(lengthChildren.subList(1, lengthChildren.size()));
+        case CTFParser.STREAM:
+            return StreamScopeParser.INSTANCE.parse(null, new StreamScopeParser.Param(lengthChildren.subList(1, lengthChildren.size())));
+        default:
+            throw new ParseException("Unsupported scope trace." + nextElem); //$NON-NLS-1$
+        }
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/trace/UUIDParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/trace/UUIDParser.java
new file mode 100644 (file)
index 0000000..e7566be
--- /dev/null
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.trace;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isAnyUnaryString;
+
+import java.util.UUID;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.UnaryStringParser;
+
+/**
+ * <strong>Trace UUID</strong>, used to ensure the event packet match the
+ * metadata used. Note: we cannot use a metadata checksum in every cases instead
+ * of a UUID because metadata can be appended to while tracing is active. This
+ * field is optional.
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public class UUIDParser implements ICommonTreeParser {
+
+    private static final String INVALID_FORMAT_FOR_UUID = "Invalid format for UUID"; //$NON-NLS-1$
+    private static final String INVALID_VALUE_FOR_UUID = "Invalid value for UUID"; //$NON-NLS-1$
+    /** Instance */
+    public static final UUIDParser INSTANCE = new UUIDParser();
+
+    private UUIDParser() {
+    }
+
+    /**
+     * Parse a UUID String and get a {@link UUID} in return.
+     *
+     * @param tree
+     *            the UUID AST
+     * @param unused
+     *            unused
+     * @return a {@link UUID}
+     * @throws ParseException
+     *             the AST was malformed
+     */
+    @Override
+    public UUID parse(CommonTree tree, ICommonTreeParserParameter unused) throws ParseException {
+
+        CommonTree firstChild = (CommonTree) tree.getChild(0);
+
+        if (isAnyUnaryString(firstChild)) {
+            if (tree.getChildCount() > 1) {
+                throw new ParseException(INVALID_VALUE_FOR_UUID);
+            }
+
+            String uuidstr = UnaryStringParser.INSTANCE.parse(firstChild, null);
+
+            try {
+                return UUID.fromString(uuidstr);
+            } catch (IllegalArgumentException e) {
+                throw new ParseException(INVALID_FORMAT_FOR_UUID, e);
+            }
+        }
+        throw new ParseException(INVALID_VALUE_FOR_UUID);
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/trace/VersionNumberParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/trace/VersionNumberParser.java
new file mode 100644 (file)
index 0000000..2935333
--- /dev/null
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.trace;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isUnaryInteger;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ICommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.UnaryIntegerParser;
+
+/**
+ * A version number parser looking up major/minor
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public final class VersionNumberParser implements ICommonTreeParser {
+
+    private static final String ERROR = "Invalid value for major/minor"; //$NON-NLS-1$
+
+    /**
+     * The instance
+     */
+    public static final VersionNumberParser INSTANCE = new VersionNumberParser();
+
+    private VersionNumberParser() {
+    }
+
+    /**
+     * Parse a version and get the major or minor value
+     *
+     * @param tree
+     *            the AST node of the version
+     * @param unused
+     *            unused
+     * @return the version value as a {@link Long}
+     * @throws ParseException
+     *             the AST is malformed
+     */
+    @Override
+    public Long parse(CommonTree tree, ICommonTreeParserParameter unused) throws ParseException {
+
+        CommonTree firstChild = (CommonTree) tree.getChild(0);
+
+        if (isUnaryInteger(firstChild)) {
+            if (tree.getChildCount() > 1) {
+                throw new ParseException(ERROR);
+            }
+            long version = UnaryIntegerParser.INSTANCE.parse(firstChild, null);
+            if (version < 0) {
+                throw new ParseException(ERROR);
+            }
+            return version;
+        }
+        throw new ParseException(ERROR);
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/variant/VariantBodyParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/variant/VariantBodyParser.java
new file mode 100644 (file)
index 0000000..da14fec
--- /dev/null
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.variant;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.childTypeError;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.jdt.annotation.Nullable;
+import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.VariantDeclaration;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.MetadataStrings;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TypeAliasParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TypedefParser;
+
+/**
+ * Variant body parser. This handles all the inside of a variant, so it handles
+ * everything between the '{' and '}' of a TSDL variant declaration.
+ *
+ * @author Matthew Khouzam
+ *
+ */
+public class VariantBodyParser extends AbstractScopedCommonTreeParser {
+
+    /**
+     * Parameter object
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+        private final DeclarationScope fDeclarationScope;
+        private final @Nullable String fName;
+        private final VariantDeclaration fVariantDeclaration;
+        private final CTFTrace fTrace;
+
+        /**
+         * Constructor
+         *
+         * @param variantDeclaration
+         *            the declaration to populate
+         * @param trace
+         *            the trace
+         * @param name
+         *            the variant name
+         * @param scope
+         *            the current scope
+         */
+        public Param(VariantDeclaration variantDeclaration, CTFTrace trace, @Nullable String name, DeclarationScope scope) {
+            fVariantDeclaration = variantDeclaration;
+            fTrace = trace;
+            fDeclarationScope = scope;
+            fName = name;
+        }
+    }
+
+    /**
+     * The instance
+     */
+    public final static VariantBodyParser INSTANCE = new VariantBodyParser();
+
+    private VariantBodyParser() {
+    }
+
+    /**
+     * Parse the variant body, fills the variant with the results.
+     *
+     * @param variantBody
+     *            the variant body AST node
+     * @param param
+     *            the {@link Param} parameter object
+     * @return a populated {@link VariantDeclaration}
+     * @throws ParseException
+     *             if the AST is malformed
+     */
+    @Override
+    public VariantDeclaration parse(CommonTree variantBody, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+
+        String variantName = ((Param) param).fName;
+        VariantDeclaration variantDeclaration = ((Param) param).fVariantDeclaration;
+        List<CommonTree> variantDeclarations = variantBody.getChildren();
+
+        final DeclarationScope scope = new DeclarationScope(((Param) param).fDeclarationScope, variantName == null ? MetadataStrings.VARIANT : variantName);
+        CTFTrace trace = ((Param) param).fTrace;
+        for (CommonTree declarationNode : variantDeclarations) {
+            switch (declarationNode.getType()) {
+            case CTFParser.TYPEALIAS:
+                TypeAliasParser.INSTANCE.parse(declarationNode, new TypeAliasParser.Param(trace, scope));
+                break;
+            case CTFParser.TYPEDEF:
+                Map<String, IDeclaration> decs = TypedefParser.INSTANCE.parse(declarationNode, new TypedefParser.Param(trace, scope));
+                for (Entry<String, IDeclaration> declarationEntry : decs.entrySet()) {
+                    variantDeclaration.addField(declarationEntry.getKey(), declarationEntry.getValue());
+                }
+                break;
+            case CTFParser.SV_DECLARATION:
+                VariantDeclarationParser.INSTANCE.parse(declarationNode, new VariantDeclarationParser.Param(variantDeclaration, trace, scope));
+                break;
+            default:
+                throw childTypeError(declarationNode);
+            }
+        }
+
+        return variantDeclaration;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/variant/VariantDeclarationParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/variant/VariantDeclarationParser.java
new file mode 100644 (file)
index 0000000..985699d
--- /dev/null
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.variant;
+
+import java.util.List;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.VariantDeclaration;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TypeDeclaratorParser;
+
+/**
+ * This parses the (sub)declarations located IN a variant declaration.
+ *
+ * @author Matthew Khouzam
+ * @author Efficios - Javadoc
+ *
+ */
+public class VariantDeclarationParser extends AbstractScopedCommonTreeParser {
+
+    /**
+     * Parameter Object
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+        private final VariantDeclaration fVariant;
+        private final DeclarationScope fDeclarationScope;
+        private final CTFTrace fTrace;
+
+        /**
+         * Parameter Object Contructor
+         *
+         * @param variant
+         *            variant declaration to populate
+         * @param trace
+         *            trace
+         * @param scope
+         *            current scope
+         */
+        public Param(VariantDeclaration variant, CTFTrace trace, DeclarationScope scope) {
+            fVariant = variant;
+            fTrace = trace;
+            fDeclarationScope = scope;
+        }
+    }
+
+    /**
+     * Instance
+     */
+    public final static VariantDeclarationParser INSTANCE = new VariantDeclarationParser();
+
+    private VariantDeclarationParser() {
+    }
+
+    /**
+     * Parses the variant declaration and gets a {@link VariantDeclaration}
+     * back.
+     *
+     * @param declaration
+     *            the variant declaration AST node
+     * @param param
+     *            the {@link Param} parameter object
+     * @return the {@link VariantDeclaration}
+     * @throws ParseException
+     *             if the AST is malformed
+     */
+    @Override
+    public VariantDeclaration parse(CommonTree declaration, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        VariantDeclaration variant = ((Param) param).fVariant;
+        final DeclarationScope scope = ((Param) param).fDeclarationScope;
+        /* Get the type specifier list node */
+        CommonTree typeSpecifierListNode = (CommonTree) declaration.getFirstChildWithType(CTFParser.TYPE_SPECIFIER_LIST);
+        if (typeSpecifierListNode == null) {
+            throw new ParseException("Variant need type specifiers"); //$NON-NLS-1$
+        }
+
+        /* Get the type declarator list node */
+        CommonTree typeDeclaratorListNode = (CommonTree) declaration.getFirstChildWithType(CTFParser.TYPE_DECLARATOR_LIST);
+        if (typeDeclaratorListNode == null) {
+            throw new ParseException("Cannot have empty variant"); //$NON-NLS-1$
+        }
+        /* Get the type declarator list */
+        List<CommonTree> typeDeclaratorList = typeDeclaratorListNode.getChildren();
+
+        /*
+         * For each type declarator, parse the declaration and add a field to
+         * the variant
+         */
+        for (CommonTree typeDeclaratorNode : typeDeclaratorList) {
+
+            StringBuilder identifierSB = new StringBuilder();
+            CTFTrace trace = ((Param) param).fTrace;
+            IDeclaration decl = TypeDeclaratorParser.INSTANCE.parse(typeDeclaratorNode,
+                    new TypeDeclaratorParser.Param(trace, typeSpecifierListNode, scope, identifierSB));
+
+            String name = identifierSB.toString();
+
+            if (variant.hasField(name)) {
+                throw new ParseException("variant: duplicate field " //$NON-NLS-1$
+                        + name);
+            }
+
+            scope.registerIdentifier(name, decl);
+
+            variant.addField(name, decl);
+        }
+        return variant;
+    }
+
+}
diff --git a/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/variant/VariantParser.java b/ctf/org.eclipse.tracecompass.ctf.core/src/org/eclipse/tracecompass/internal/ctf/core/event/metadata/tsdl/variant/VariantParser.java
new file mode 100644 (file)
index 0000000..964ac7c
--- /dev/null
@@ -0,0 +1,350 @@
+/*******************************************************************************
+ * Copyright (c) 2015 Ericsson
+ *
+ * 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
+ *******************************************************************************/
+package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.variant;
+
+import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.childTypeError;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.antlr.runtime.tree.CommonTree;
+import org.eclipse.jdt.annotation.NonNullByDefault;
+import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
+import org.eclipse.tracecompass.ctf.core.event.types.EnumDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
+import org.eclipse.tracecompass.ctf.core.event.types.VariantDeclaration;
+import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
+import org.eclipse.tracecompass.ctf.parser.CTFParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
+
+/**
+ *
+ * A CTF variant is a selection between different types. A CTF variant must
+ * always be defined within the scope of a structure or within fields contained
+ * within a structure (defined recursively). A _tag_ enumeration field must
+ * appear in either the same static scope, prior to the variant field (in field
+ * declaration order), in an upper static scope, or in an upper dynamic scope
+ * (see [Static and dynamic scopes](#spec7.3.2)). The type selection is
+ * indicated by the mapping from the enumeration value to the string used as
+ * variant type selector. The field to use as tag is specified by the
+ * `tag_field`, specified between `< >` after the `variant` keyword for unnamed
+ * variants, and after _variant name_ for named variants. It is not required
+ * that each enumeration mapping appears as variant type tag field. It is also
+ * not required that each variant type tag appears as enumeration mapping.
+ * However, it is required that any enumeration mapping encountered within a
+ * stream has a matching variant type tag field. <br>
+ * The alignment of the variant is the alignment of the type as selected by the
+ * tag value for the specific instance of the variant. The size of the variant
+ * is the size as selected by the tag value for the specific instance of the
+ * variant. <br>
+ * The alignment of the type containing the variant is independent of the
+ * variant alignment. For instance, if a structure contains two fields, a 32-bit
+ * integer, aligned on 32 bits, and a variant, which contains two choices:
+ * either a 32-bit field, aligned on 32 bits, or a 64-bit field, aligned on 64
+ * bits, the alignment of the outmost structure will be 32-bit (the alignment of
+ * its largest field, disregarding the alignment of the variant). The alignment
+ * of the variant will depend on the selector: if the variant's 32-bit field is
+ * selected, its alignment will be 32-bit, or 64-bit otherwise. It is important
+ * to note that variants are specifically tailored for compactness in a stream.
+ * Therefore, the relative offsets of compound type fields can vary depending on
+ * the offset at which the compound type starts if it contains a variant that
+ * itself contains a type with alignment larger than the largest field contained
+ * within the compound type. This is caused by the fact that the compound type
+ * may contain the enumeration that select the variant's choice, and therefore
+ * the alignment to be applied to the compound type cannot be determined before
+ * encountering the enumeration. <br>
+ * Each variant type selector possess a field name, which is a unique identifier
+ * within the variant. The identifier is not allowed to use any [reserved
+ * keyword](#C.1.2). Replacing reserved keywords with underscore-prefixed field
+ * names is recommended. Fields starting with an underscore should have their
+ * leading underscore removed by the CTF trace readers. <br>
+ * A named variant declaration followed by its definition within a structure
+ * declaration: <br>
+ *
+ * <pre>
+variant name {
+    field_type sel1;
+    field_type sel2;
+    field_type sel3;
+    // ...
+};
+
+struct {
+    enum : integer_type { sel1, sel2, sel3, <em>more</em> } tag_field;
+    // ...
+    variant name <tag_field> v;
+}
+ * </pre>
+ *
+ * An unnamed variant definition within a structure is expressed by the
+ * following TSDL metadata: <br>
+ *
+ * <pre>
+struct {
+    enum : integer_type { sel1, sel2, sel3, <em>more</em> } tag_field;
+    // ...
+    variant <tag_field> {
+        field_type sel1;
+        field_type sel2;
+        field_type sel3;
+        // ...
+    } v;
+}
+ * </pre>
+ *
+ * Example of a named variant within a sequence that refers to a single tag
+ * field: <br>
+ *
+ * <pre>
+variant example {
+    uint32_t a;
+    uint64_t b;
+    short c;
+};
+
+struct {
+    enum : uint2_t { a, b, c } choice;
+    unsigned int seqlen;
+    variant example <choice> v[seqlen];
+}
+ * </pre>
+ *
+ * Example of an unnamed variant: <br>
+ *
+ * <pre>
+struct {
+    enum : uint2_t { a, b, c, d } choice;
+
+    // Unrelated fields can be added between the variant and its tag
+    int32_t somevalue;
+    variant <choice> {
+        uint32_t a;
+        uint64_t b;
+        short c;
+        struct {
+            unsigned int field1;
+            uint64_t field2;
+        } d;
+    } s;
+}
+ * </pre>
+ *
+ * Example of an unnamed variant within an array: <br>
+ *
+ * <pre>
+struct {
+    enum : uint2_t { a, b, c } choice;
+    variant <choice> {
+        uint32_t a;
+        uint64_t b;
+        short c;
+    } v[10];
+}
+ * </pre>
+ *
+ * <br>
+ * Example of a variant type definition within a structure, where the defined
+ * type is then declared within an array of structures. This variant refers to a
+ * tag located in an upper static scope. This example clearly shows that a
+ * variant type definition referring to the tag `x` uses the closest preceding
+ * field from the static scope of the type definition. <br>
+ *
+ * <pre>
+struct {
+    enum : uint2_t { a, b, c, d } x;
+
+     // "x" refers to the preceding "x" enumeration in the
+     // static scope of the type definition.
+
+    typedef variant <x> {
+      uint32_t a;
+      uint64_t b;
+      short c;
+    } example_variant;
+
+    struct {
+      enum : int { x, y, z } x; // This enumeration is not used by "v".
+
+      // "v" uses the "enum : uint2_t { a, b, c, d }" tag.
+      example_variant v;
+    } a[10];
+}
+ * </pre>
+ *
+ * @author Matthew Khouzam
+ * @author Efficios - Javadoc preamble
+ *
+ *
+ */
+public class VariantParser extends AbstractScopedCommonTreeParser {
+
+    /**
+     * Parameter object with a trace and current scope
+     *
+     * @author Matthew Khouzam
+     *
+     */
+    @NonNullByDefault
+    public static final class Param implements ICommonTreeParserParameter {
+        private final DeclarationScope fDeclarationScope;
+        private final CTFTrace fTrace;
+
+        /**
+         * Constructor
+         *
+         * @param trace
+         *            the trace
+         * @param scope
+         *            the current scope
+         */
+        public Param(CTFTrace trace, DeclarationScope scope) {
+            fTrace = trace;
+            fDeclarationScope = scope;
+        }
+    }
+
+    /**
+     * The instance
+     */
+    public final static VariantParser INSTANCE = new VariantParser();
+
+    private VariantParser() {
+    }
+
+    /**
+     * Parse the variant
+     *
+     * @param variant
+     *            the variant AST node
+     * @param param
+     *            the {@link Param} parameter object
+     * @return a populated {@link VariantDeclaration}
+     * @throws ParseException
+     *             the AST is malformed
+     */
+    @Override
+    public VariantDeclaration parse(CommonTree variant, ICommonTreeParserParameter param) throws ParseException {
+        if (!(param instanceof Param)) {
+            throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
+        }
+        final DeclarationScope scope = ((Param) param).fDeclarationScope;
+
+        List<CommonTree> children = variant.getChildren();
+        VariantDeclaration variantDeclaration = null;
+
+        boolean hasName = false;
+        String variantName = null;
+
+        boolean hasBody = false;
+        CommonTree variantBody = null;
+
+        boolean hasTag = false;
+        String variantTag = null;
+
+        for (CommonTree child : children) {
+            switch (child.getType()) {
+            case CTFParser.VARIANT_NAME:
+
+                hasName = true;
+
+                CommonTree variantNameIdentifier = (CommonTree) child.getChild(0);
+
+                variantName = variantNameIdentifier.getText();
+
+                break;
+            case CTFParser.VARIANT_TAG:
+
+                hasTag = true;
+
+                CommonTree variantTagIdentifier = (CommonTree) child.getChild(0);
+
+                variantTag = variantTagIdentifier.getText();
+
+                break;
+            case CTFParser.VARIANT_BODY:
+
+                hasBody = true;
+
+                variantBody = child;
+
+                break;
+            default:
+                throw childTypeError(child);
+            }
+        }
+
+        if (hasBody) {
+            /*
+             * If variant has a name, check if already defined in the current
+             * scope.
+             */
+            if (hasName
+                    && (scope.lookupVariant(variantName) != null)) {
+                throw new ParseException("variant " + variantName //$NON-NLS-1$
+                        + " already defined."); //$NON-NLS-1$
+            }
+
+            /* Create the declaration */
+            variantDeclaration = new VariantDeclaration();
+
+            CTFTrace trace = ((Param) param).fTrace;
+            /* Parse the body */
+            VariantBodyParser.INSTANCE.parse(variantBody, new VariantBodyParser.Param(variantDeclaration, trace, variantName, scope));
+
+            /* If variant has name, add it to the current scope. */
+            if (hasName) {
+                scope.registerVariant(variantName, variantDeclaration);
+            }
+        } else /* !hasBody */ {
+            if (hasName) {
+                /* Name and !body */
+
+                /* Lookup the name in the current scope. */
+                variantDeclaration = scope.lookupVariantRecursive(variantName);
+
+                /*
+                 * If not found, it means that a struct with such name has not
+                 * been defined
+                 */
+                if (variantDeclaration == null) {
+                    throw new ParseException("variant " + variantName //$NON-NLS-1$
+                            + " is not defined"); //$NON-NLS-1$
+                }
+            } else {
+                /* !Name and !body */
+
+                /* We can't do anything with that. */
+                throw new ParseException("variant with no name and no body"); //$NON-NLS-1$
+            }
+        }
+
+        if (hasTag) {
+            variantDeclaration.setTag(variantTag);
+
+            IDeclaration decl = scope.lookupIdentifierRecursive(variantTag);
+            if (decl == null) {
+                throw new ParseException("Variant tag not found: " + variantTag); //$NON-NLS-1$
+            }
+            if (!(decl instanceof EnumDeclaration)) {
+                throw new ParseException("Variant tag must be an enum: " + variantTag); //$NON-NLS-1$
+            }
+            EnumDeclaration tagDecl = (EnumDeclaration) decl;
+            Set<String> intersection = new HashSet<>(tagDecl.getLabels());
+            intersection.retainAll(variantDeclaration.getFields().keySet());
+            if (intersection.isEmpty()) {
+                throw new ParseException("Variant contains no values of the tag, impossible to use: " + variantName); //$NON-NLS-1$
+            }
+        }
+
+        return variantDeclaration;
+    }
+
+}
index b434e4cdbb6e5edbd48914e798c4f826f04878b2..663dae05e816ddff22f32d2e3d0a640741434e53 100644 (file)
@@ -30,7 +30,7 @@ import org.eclipse.tracecompass.ctf.core.trace.CTFStreamInput;
 import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
 import org.eclipse.tracecompass.ctf.core.trace.ICTFStream;
 import org.eclipse.tracecompass.internal.ctf.core.event.EventDeclaration;
-import org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException;
+import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
 
 /**
  * <b><u>Stream</u></b>
index ea46b6551f402fa708783cd255ab83d5a0652427..84de7488b0f3e55c1faa3350aad173cc6c5f01e5 100644 (file)
@@ -28,9 +28,9 @@ 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.
+ * 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
  */
@@ -63,12 +63,12 @@ public class CtfParserTest {
             }
             if (tree.getType() != fType) {
                 fail("Type mismatch!" +
-                     " expected:" + fType +
-                     " actual:" + tree.getType());
+                        " expected:" + fType +
+                        " actual:" + tree.getType());
             }
 
             if (fText != null) {
-                if (tree.getText().compareTo(fText) != 0) {
+                if (!fText.equals(tree.getText())) {
                     fail("Text mismatch!" +
                             " expected:" + fText +
                             " actual:" + tree.getText());
@@ -85,8 +85,8 @@ public class CtfParserTest {
                 } else {
                     if (tree.getChildren().size() != size) {
                         fail("Invalid number of childs!"
-                             + " expected:" + size
-                             + " actual:" + tree.getChildren().size());
+                                + " expected:" + size
+                                + " actual:" + tree.getChildren().size());
                     }
 
                     for (int i = 0; i < size; ++i) {
@@ -162,7 +162,6 @@ public class CtfParserTest {
     // Test cases
     // ------------------------------------------------------------------------
 
-
     /**
      * Validate that parsing of an empty expression is invalid.
      */
@@ -178,44 +177,44 @@ public class CtfParserTest {
     @Test
     public void testIntegerLiteralPrimaryExpression() {
         Matches(Node(CTFParser.UNARY_EXPRESSION_DEC,
-                     Node(CTFParser.DECIMAL_LITERAL, "123")),
+                Node(CTFParser.DECIMAL_LITERAL, "123")),
                 primaryExpression("123"));
 
         Matches(Node(CTFParser.UNARY_EXPRESSION_HEX,
-                     Node(CTFParser.HEX_LITERAL, "0x123")),
+                Node(CTFParser.HEX_LITERAL, "0x123")),
                 primaryExpression("0x123"));
 
         Matches(Node(CTFParser.UNARY_EXPRESSION_OCT,
-                     Node(CTFParser.OCTAL_LITERAL, "0123")),
+                Node(CTFParser.OCTAL_LITERAL, "0123")),
                 primaryExpression("0123"));
 
         Matches(Node(CTFParser.UNARY_EXPRESSION_DEC,
-                     Node(CTFParser.DECIMAL_LITERAL, "123"),
-                     Node(CTFParser.SIGN, "-")),
+                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.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, "+")),
+                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, "-")),
+                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, "-")),
+                Node(CTFParser.OCTAL_LITERAL, "0123"),
+                Node(CTFParser.SIGN, "+"),
+                Node(CTFParser.SIGN, "-")),
                 primaryExpression("+ - 0123"));
     }
 
@@ -237,15 +236,15 @@ public class CtfParserTest {
     @Test
     public void testStringLiteralPrimaryExpression() {
         Matches(Node(CTFParser.UNARY_EXPRESSION_STRING_QUOTES,
-                     Node(CTFParser.STRING_LITERAL, "\"aaa\"")),
+                Node(CTFParser.STRING_LITERAL, "\"aaa\"")),
                 primaryExpression("\"aaa\""));
 
         Matches(Node(CTFParser.UNARY_EXPRESSION_STRING_QUOTES,
-                     Node(CTFParser.STRING_LITERAL, "L\"aaa\"")),
+                Node(CTFParser.STRING_LITERAL, "L\"aaa\"")),
                 primaryExpression("L\"aaa\""));
 
         Matches(Node(CTFParser.UNARY_EXPRESSION_STRING_QUOTES,
-                     Node(CTFParser.STRING_LITERAL, "\"aaa\\n\"")),
+                Node(CTFParser.STRING_LITERAL, "\"aaa\\n\"")),
                 primaryExpression("\"aaa\\n\""));
     }
 
@@ -255,10 +254,10 @@ public class CtfParserTest {
     @Test
     public void testKeywordPrimaryExpression() {
         Matches(Node(CTFParser.UNARY_EXPRESSION_STRING,
-                     Node(CTFParser.SIGNEDTOK, "signed")),
+                Node(CTFParser.SIGNEDTOK, "signed")),
                 primaryExpression("signed"));
         Matches(Node(CTFParser.UNARY_EXPRESSION_STRING,
-                     Node(CTFParser.ALIGNTOK, "align")),
+                Node(CTFParser.ALIGNTOK, "align")),
                 primaryExpression("align"));
     }
 
@@ -268,10 +267,10 @@ public class CtfParserTest {
     @Test
     public void testIdentifierPrimaryExpression() {
         Matches(Node(CTFParser.UNARY_EXPRESSION_STRING,
-                     Node(CTFParser.IDENTIFIER, "x")),
+                Node(CTFParser.IDENTIFIER, "x")),
                 primaryExpression("x"));
         Matches(Node(CTFParser.UNARY_EXPRESSION_STRING,
-                     Node(CTFParser.IDENTIFIER, "_123")),
+                Node(CTFParser.IDENTIFIER, "_123")),
                 primaryExpression("_123"));
     }
 
@@ -290,11 +289,11 @@ public class CtfParserTest {
     @Test
     public void testSimpleUnaryExpression() {
         Matches(Node(CTFParser.UNARY_EXPRESSION_DEC,
-                     Node(CTFParser.DECIMAL_LITERAL, "123")),
+                Node(CTFParser.DECIMAL_LITERAL, "123")),
                 unaryExpression("123"));
 
         Matches(Node(CTFParser.UNARY_EXPRESSION_STRING,
-                     Node(CTFParser.IDENTIFIER, "x")),
+                Node(CTFParser.IDENTIFIER, "x")),
                 unaryExpression("x"));
     }
 
@@ -304,38 +303,38 @@ public class CtfParserTest {
     @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"))),
+                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"))),
+                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"))),
+                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, "+"))),
+                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]"));
     }
 
@@ -346,18 +345,18 @@ public class CtfParserTest {
     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"))),
+                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"))),
+                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]"));
     }
 
@@ -367,20 +366,20 @@ public class CtfParserTest {
     @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")))),
+                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")))),
+                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"));
     }
 
@@ -390,20 +389,20 @@ public class CtfParserTest {
     @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")))),
+                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")))),
+                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"));
     }
 
@@ -413,19 +412,19 @@ public class CtfParserTest {
     @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"))),
+                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]"));
     }
 
@@ -481,39 +480,39 @@ public class CtfParserTest {
     @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"))))))),
+                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())))),
+                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())))),
+                                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())))),
+                        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 };"));
     }
 
@@ -528,39 +527,39 @@ public class CtfParserTest {
                 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")))))))),
+                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()))))),
+                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 };"));
     }
 
@@ -570,8 +569,9 @@ public class CtfParserTest {
     @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.
+        /*
+         * TODO: An exception is throw when building an common tree without
+         * assignments in the ctf-body.
          */
         Matches(All(),
                 declaration("env { };"));
@@ -589,19 +589,19 @@ public class CtfParserTest {
     @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"))))),
+                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())),
+                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;};"));
     }
 
@@ -612,41 +612,41 @@ public class CtfParserTest {
     @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"))))),
+                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"))))))),
+                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()),
+                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())),
+                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; };"));
+                        + "packet.header := struct dummy; };"));
     }
 
 }
index bd75d1023905dc8a0cab1ae3cc39b10d7d4dda38..5f4701b56cd03ca9c9774e7992c447bce3ac2fc6 100644 (file)
@@ -80,10 +80,10 @@ public class TestInvalidCtfTrace {
         ERRORS.put("integer-encoding-invalid", "Invalid value for encoding");
         ERRORS.put("integer-negative-bit-size", "Invalid value for size");
         ERRORS.put("integer-range", "Invalid integer format: 23452397856348975623897562893746589237465289374658923764598237645897234658723648579236");
-        ERRORS.put("integer-signed-as-string", "org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException");
+        ERRORS.put("integer-signed-as-string", "Invalid boolean value");
         ERRORS.put("integer-signed-invalid", "Invalid boolean value svp");
         ERRORS.put("integer-size-as-string", "Invalid value for size");
-        ERRORS.put("integer-size-missing", "org.eclipse.tracecompass.internal.ctf.core.event.metadata.exceptions.ParseException");
+        ERRORS.put("integer-size-missing", "Invalid boolean value");
         ERRORS.put("struct-align-enum", "Invalid value for alignment");
         ERRORS.put("struct-align-huge", "Invalid integer format: 0xFFFFFFFFU");
         ERRORS.put("struct-align-negative", "Invalid value for alignment : -8");
This page took 0.220949 seconds and 5 git commands to generate.