Revert "ctf: Remove the callsite support"
[deliverable/tracecompass.git] / ctf / org.eclipse.tracecompass.ctf.core / src / org / eclipse / tracecompass / internal / ctf / core / event / metadata / IOStructGen.java
1 /*******************************************************************************
2 * Copyright (c) 2011, 2015 Ericsson, Ecole Polytechnique de Montreal and others
3 *
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
8 *
9 * Contributors:
10 * Matthew Khouzam - Initial Design and Grammar
11 * Francis Giraldeau - Initial API and implementation
12 * Simon Marchi - Initial API and implementation
13 *******************************************************************************/
14
15 package org.eclipse.tracecompass.internal.ctf.core.event.metadata;
16
17 import java.util.ArrayList;
18 import java.util.Collection;
19 import java.util.List;
20 import java.util.stream.Collectors;
21
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;
41
42 import com.google.common.collect.Iterables;
43
44 /**
45 * IOStructGen
46 */
47 public class IOStructGen {
48
49 // ------------------------------------------------------------------------
50 // Attributes
51 // ------------------------------------------------------------------------
52
53 /**
54 * The trace
55 */
56 private final @NonNull CTFTrace fTrace;
57 private CommonTree fTree;
58
59 /**
60 * The current declaration scope.
61 */
62 private final @NonNull DeclarationScope fRoot;
63
64 /**
65 * Data helpers needed for streaming
66 */
67
68 private boolean fHasBeenParsed = false;
69
70 // ------------------------------------------------------------------------
71 // Constructor
72 // ------------------------------------------------------------------------
73
74 /**
75 * Constructor
76 *
77 * @param tree
78 * the tree (ANTLR generated) with the parsed TSDL data.
79 * @param trace
80 * the trace containing the places to put all the read metadata
81 */
82 public IOStructGen(CommonTree tree, @NonNull CTFTrace trace) {
83 fTrace = trace;
84 fTree = tree;
85 fRoot = NonNullUtils.checkNotNull(trace.getScope());
86 }
87
88 /**
89 * Parse the tree and populate the trace defined in the constructor.
90 *
91 * @throws ParseException
92 * If there was a problem parsing the metadata
93 */
94 public void generate() throws ParseException {
95 parseRoot(fTree);
96 }
97
98 /**
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
101 * thus
102 *
103 * @throws ParseException
104 * If there was a problem parsing the metadata
105 */
106 public void generateFragment() throws ParseException {
107 parseIncompleteRoot(fTree);
108 }
109
110 // ------------------------------------------------------------------------
111 // Operations
112 // ------------------------------------------------------------------------
113
114 /**
115 * Sets a new tree to parse
116 *
117 * @param newTree
118 * the new tree to parse
119 */
120 public void setTree(CommonTree newTree) {
121 fTree = newTree;
122 }
123
124 /**
125 * Parse the root node.
126 *
127 * @param root
128 * A ROOT node.
129 * @throws ParseException
130 */
131 private void parseRoot(CommonTree root) throws ParseException {
132
133 List<CommonTree> children = root.getChildren();
134
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();
141 switch (type) {
142 case CTFParser.DECLARATION:
143 parseRootDeclaration(child);
144 break;
145 case CTFParser.TRACE:
146 if (traceNode != null) {
147 throw new ParseException("Only one trace block is allowed"); //$NON-NLS-1$
148 }
149 traceNode = child;
150 parseTrace(traceNode);
151 break;
152 case CTFParser.STREAM:
153 StreamParser.INSTANCE.parse(child, new StreamParser.Param(fTrace, fRoot));
154 hasStreams = true;
155 break;
156 case CTFParser.EVENT:
157 events.add(child);
158 break;
159 case CTFParser.CLOCK:
160 CTFClock ctfClock = ClockParser.INSTANCE.parse(child, null);
161 String nameValue = ctfClock.getName();
162 fTrace.addClock(nameValue, ctfClock);
163 break;
164 case CTFParser.ENV:
165 fTrace.setEnvironment(EnvironmentParser.INSTANCE.parse(child, null));
166 break;
167 case CTFParser.CALLSITE:
168 callsites.add(CallSiteParser.INSTANCE.parse(child, null));
169 break;
170 default:
171 throw childTypeError(child);
172 }
173 }
174 if (traceNode == null) {
175 throw new ParseException("Missing trace block"); //$NON-NLS-1$
176 }
177 parseEvents(events, callsites, hasStreams);
178 fHasBeenParsed = true;
179 }
180
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));
185 }
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);
190
191 }
192 }
193
194 private void parseIncompleteRoot(CommonTree root) throws ParseException {
195 if (!fHasBeenParsed) {
196 throw new ParseException("You need to run generate first"); //$NON-NLS-1$
197 }
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();
203 switch (type) {
204 case CTFParser.DECLARATION:
205 parseRootDeclaration(child);
206 break;
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));
211 break;
212 case CTFParser.EVENT:
213 events.add(child);
214 break;
215 case CTFParser.CLOCK:
216 CTFClock ctfClock = ClockParser.INSTANCE.parse(child, null);
217 String nameValue = ctfClock.getName();
218 fTrace.addClock(nameValue, ctfClock);
219 break;
220 case CTFParser.ENV:
221 fTrace.setEnvironment(EnvironmentParser.INSTANCE.parse(child, null));
222 break;
223 case CTFParser.CALLSITE:
224 callsites.add(CallSiteParser.INSTANCE.parse(child, null));
225 break;
226 default:
227 throw childTypeError(child);
228 }
229 }
230 parseEvents(events, callsites, !Iterables.isEmpty(fTrace.getStreams()));
231 }
232
233 private void parseTrace(CommonTree traceNode) throws ParseException {
234
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$
239 }
240
241 for (CommonTree child : children) {
242 switch (child.getType()) {
243 case CTFParser.TYPEALIAS:
244 TypeAliasParser.INSTANCE.parse(child, new TypeAliasParser.Param(trace, fRoot));
245 break;
246 case CTFParser.TYPEDEF:
247 TypedefParser.INSTANCE.parse(child, new TypedefParser.Param(trace, fRoot));
248 break;
249 case CTFParser.CTF_EXPRESSION_TYPE:
250 case CTFParser.CTF_EXPRESSION_VAL:
251 TraceDeclarationParser.INSTANCE.parse(child, new TraceDeclarationParser.Param(fTrace, fRoot));
252 break;
253 default:
254 throw childTypeError(child);
255 }
256 }
257
258 /*
259 * If trace byte order was not specified and not using packet based
260 * metadata
261 */
262 if (fTrace.getByteOrder() == null) {
263 throw new ParseException("Trace byte order not set"); //$NON-NLS-1$
264 }
265 }
266
267 /**
268 * Parses a declaration at the root level.
269 *
270 * @param declaration
271 * The declaration subtree.
272 * @throws ParseException
273 */
274 private void parseRootDeclaration(CommonTree declaration)
275 throws ParseException {
276
277 List<CommonTree> children = declaration.getChildren();
278
279 for (CommonTree child : children) {
280 switch (child.getType()) {
281 case CTFParser.TYPEDEF:
282 TypedefParser.INSTANCE.parse(child, new TypedefParser.Param(fTrace, fRoot));
283 break;
284 case CTFParser.TYPEALIAS:
285 TypeAliasParser.INSTANCE.parse(child, new TypeAliasParser.Param(fTrace, fRoot));
286 break;
287 case CTFParser.TYPE_SPECIFIER_LIST:
288 TypeSpecifierListParser.INSTANCE.parse(child, new TypeSpecifierListParser.Param(fTrace, null, null, fRoot));
289 break;
290 default:
291 throw childTypeError(child);
292 }
293 }
294 }
295
296 /**
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.
300 *
301 * @param child
302 * The invalid child node.
303 * @return ParseException with details
304 */
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$
310
311 return new ParseException(error);
312 }
313
314 }
This page took 0.058414 seconds and 5 git commands to generate.