1 /*******************************************************************************
2 * Copyright (c) 2011, 2015 Ericsson, Ecole Polytechnique de Montreal and others
4 * All rights reserved. This program and the accompanying materials are made
5 * available under the terms of the Eclipse Public License v1.0 which
6 * accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * Matthew Khouzam - Initial Design and Grammar
11 * Francis Giraldeau - Initial API and implementation
12 * Simon Marchi - Initial API and implementation
13 *******************************************************************************/
15 package org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.metadata
;
17 import java
.util
.ArrayList
;
18 import java
.util
.Collection
;
19 import java
.util
.List
;
20 import java
.util
.stream
.Collectors
;
22 import org
.antlr
.runtime
.tree
.CommonTree
;
23 import org
.eclipse
.jdt
.annotation
.NonNull
;
24 import org
.eclipse
.tracecompass
.common
.core
.NonNullUtils
;
25 import org
.eclipse
.tracecompass
.ctf
.core
.event
.CTFCallsite
;
26 import org
.eclipse
.tracecompass
.ctf
.core
.event
.CTFClock
;
27 import org
.eclipse
.tracecompass
.ctf
.core
.event
.metadata
.DeclarationScope
;
28 import org
.eclipse
.tracecompass
.ctf
.core
.trace
.CTFTrace
;
29 import org
.eclipse
.tracecompass
.ctf
.parser
.CTFParser
;
30 import org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.EventDeclaration
;
31 import org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.metadata
.tsdl
.ClockParser
;
32 import org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.metadata
.tsdl
.TypeAliasParser
;
33 import org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.metadata
.tsdl
.TypeSpecifierListParser
;
34 import org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.metadata
.tsdl
.TypedefParser
;
35 import org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.metadata
.tsdl
.callsite
.CallSiteParser
;
36 import org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.metadata
.tsdl
.environment
.EnvironmentParser
;
37 import org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.metadata
.tsdl
.event
.EventParser
;
38 import org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.metadata
.tsdl
.stream
.StreamParser
;
39 import org
.eclipse
.tracecompass
.internal
.ctf
.core
.event
.metadata
.tsdl
.trace
.TraceDeclarationParser
;
40 import org
.eclipse
.tracecompass
.internal
.ctf
.core
.trace
.CTFStream
;
42 import com
.google
.common
.collect
.Iterables
;
47 public class IOStructGen
{
49 // ------------------------------------------------------------------------
51 // ------------------------------------------------------------------------
56 private final @NonNull CTFTrace fTrace
;
57 private CommonTree fTree
;
60 * The current declaration scope.
62 private final @NonNull DeclarationScope fRoot
;
65 * Data helpers needed for streaming
68 private boolean fHasBeenParsed
= false;
70 // ------------------------------------------------------------------------
72 // ------------------------------------------------------------------------
78 * the tree (ANTLR generated) with the parsed TSDL data.
80 * the trace containing the places to put all the read metadata
82 public IOStructGen(CommonTree tree
, @NonNull CTFTrace trace
) {
85 fRoot
= NonNullUtils
.checkNotNull(trace
.getScope());
89 * Parse the tree and populate the trace defined in the constructor.
91 * @throws ParseException
92 * If there was a problem parsing the metadata
94 public void generate() throws ParseException
{
99 * Parse a partial tree and populate the trace defined in the constructor.
100 * Does not check for a "trace" block as there is only one in the trace and
103 * @throws ParseException
104 * If there was a problem parsing the metadata
106 public void generateFragment() throws ParseException
{
107 parseIncompleteRoot(fTree
);
110 // ------------------------------------------------------------------------
112 // ------------------------------------------------------------------------
115 * Sets a new tree to parse
118 * the new tree to parse
120 public void setTree(CommonTree newTree
) {
125 * Parse the root node.
129 * @throws ParseException
131 private void parseRoot(CommonTree root
) throws ParseException
{
133 List
<CommonTree
> children
= root
.getChildren();
135 CommonTree traceNode
= null;
136 boolean hasStreams
= false;
137 List
<CommonTree
> events
= new ArrayList
<>();
138 Collection
<CTFCallsite
> callsites
= new ArrayList
<>();
139 for (CommonTree child
: children
) {
140 final int type
= child
.getType();
142 case CTFParser
.DECLARATION
:
143 parseRootDeclaration(child
);
145 case CTFParser
.TRACE
:
146 if (traceNode
!= null) {
147 throw new ParseException("Only one trace block is allowed"); //$NON-NLS-1$
150 parseTrace(traceNode
);
152 case CTFParser
.STREAM
:
153 StreamParser
.INSTANCE
.parse(child
, new StreamParser
.Param(fTrace
, fRoot
));
156 case CTFParser
.EVENT
:
159 case CTFParser
.CLOCK
:
160 CTFClock ctfClock
= ClockParser
.INSTANCE
.parse(child
, null);
161 String nameValue
= ctfClock
.getName();
162 fTrace
.addClock(nameValue
, ctfClock
);
165 fTrace
.setEnvironment(EnvironmentParser
.INSTANCE
.parse(child
, null));
167 case CTFParser
.CALLSITE
:
168 callsites
.add(CallSiteParser
.INSTANCE
.parse(child
, null));
171 throw childTypeError(child
);
174 if (traceNode
== null) {
175 throw new ParseException("Missing trace block"); //$NON-NLS-1$
177 parseEvents(events
, callsites
, hasStreams
);
178 fHasBeenParsed
= true;
181 private void parseEvents(List
<CommonTree
> events
, Collection
<CTFCallsite
> staticCallsites
, boolean hasStreams
) throws ParseException
{
182 if (!hasStreams
&& !events
.isEmpty()) {
183 /* Add an empty stream that will have a null id */
184 fTrace
.addStream(new CTFStream(fTrace
));
186 for (CommonTree event
: events
) {
187 EventDeclaration ev
= EventParser
.INSTANCE
.parse(event
, new EventParser
.Param(fTrace
, fRoot
));
188 List
<CTFCallsite
> callsites
= staticCallsites
.stream().filter(cs
-> ev
.getName().equals(cs
.getEventName())).collect(Collectors
.toList());
189 ev
.addCallsites(callsites
);
194 private void parseIncompleteRoot(CommonTree root
) throws ParseException
{
195 if (!fHasBeenParsed
) {
196 throw new ParseException("You need to run generate first"); //$NON-NLS-1$
198 List
<CommonTree
> children
= root
.getChildren();
199 List
<CommonTree
> events
= new ArrayList
<>();
200 Collection
<CTFCallsite
> callsites
= new ArrayList
<>();
201 for (CommonTree child
: children
) {
202 final int type
= child
.getType();
204 case CTFParser
.DECLARATION
:
205 parseRootDeclaration(child
);
207 case CTFParser
.TRACE
:
208 throw new ParseException("Trace block defined here, please use generate and not generateFragment to parse this fragment"); //$NON-NLS-1$
209 case CTFParser
.STREAM
:
210 StreamParser
.INSTANCE
.parse(child
, new StreamParser
.Param(fTrace
, fRoot
));
212 case CTFParser
.EVENT
:
215 case CTFParser
.CLOCK
:
216 CTFClock ctfClock
= ClockParser
.INSTANCE
.parse(child
, null);
217 String nameValue
= ctfClock
.getName();
218 fTrace
.addClock(nameValue
, ctfClock
);
221 fTrace
.setEnvironment(EnvironmentParser
.INSTANCE
.parse(child
, null));
223 case CTFParser
.CALLSITE
:
224 callsites
.add(CallSiteParser
.INSTANCE
.parse(child
, null));
227 throw childTypeError(child
);
230 parseEvents(events
, callsites
, !Iterables
.isEmpty(fTrace
.getStreams()));
233 private void parseTrace(CommonTree traceNode
) throws ParseException
{
235 CTFTrace trace
= fTrace
;
236 List
<CommonTree
> children
= traceNode
.getChildren();
237 if (children
== null) {
238 throw new ParseException("Trace block is empty"); //$NON-NLS-1$
241 for (CommonTree child
: children
) {
242 switch (child
.getType()) {
243 case CTFParser
.TYPEALIAS
:
244 TypeAliasParser
.INSTANCE
.parse(child
, new TypeAliasParser
.Param(trace
, fRoot
));
246 case CTFParser
.TYPEDEF
:
247 TypedefParser
.INSTANCE
.parse(child
, new TypedefParser
.Param(trace
, fRoot
));
249 case CTFParser
.CTF_EXPRESSION_TYPE
:
250 case CTFParser
.CTF_EXPRESSION_VAL
:
251 TraceDeclarationParser
.INSTANCE
.parse(child
, new TraceDeclarationParser
.Param(fTrace
, fRoot
));
254 throw childTypeError(child
);
259 * If trace byte order was not specified and not using packet based
262 if (fTrace
.getByteOrder() == null) {
263 throw new ParseException("Trace byte order not set"); //$NON-NLS-1$
268 * Parses a declaration at the root level.
271 * The declaration subtree.
272 * @throws ParseException
274 private void parseRootDeclaration(CommonTree declaration
)
275 throws ParseException
{
277 List
<CommonTree
> children
= declaration
.getChildren();
279 for (CommonTree child
: children
) {
280 switch (child
.getType()) {
281 case CTFParser
.TYPEDEF
:
282 TypedefParser
.INSTANCE
.parse(child
, new TypedefParser
.Param(fTrace
, fRoot
));
284 case CTFParser
.TYPEALIAS
:
285 TypeAliasParser
.INSTANCE
.parse(child
, new TypeAliasParser
.Param(fTrace
, fRoot
));
287 case CTFParser
.TYPE_SPECIFIER_LIST
:
288 TypeSpecifierListParser
.INSTANCE
.parse(child
, new TypeSpecifierListParser
.Param(fTrace
, null, null, fRoot
));
291 throw childTypeError(child
);
297 * Throws a ParseException stating that the parent-child relation between
298 * the given node and its parent is not valid. It means that the shape of
299 * the AST is unexpected.
302 * The invalid child node.
303 * @return ParseException with details
305 private static ParseException
childTypeError(CommonTree child
) {
306 CommonTree parent
= (CommonTree
) child
.getParent();
307 String error
= "Parent " + CTFParser
.tokenNames
[parent
.getType()] //$NON-NLS-1$
308 + " can't have a child of type " //$NON-NLS-1$
309 + CTFParser
.tokenNames
[child
.getType()] + "."; //$NON-NLS-1$
311 return new ParseException(error
);
This page took 0.058414 seconds and 5 git commands to generate.