ctf: fix Modifier order to always be static final
[deliverable/tracecompass.git] / ctf / org.eclipse.tracecompass.ctf.core / src / org / eclipse / tracecompass / internal / ctf / core / event / metadata / tsdl / struct / StructParser.java
1 /*******************************************************************************
2 * Copyright (c) 2015 Ericsson
3 *
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
8 *******************************************************************************/
9 package org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.struct;
10
11 import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.childTypeError;
12
13 import java.util.List;
14
15 import org.antlr.runtime.tree.CommonTree;
16 import org.eclipse.jdt.annotation.NonNullByDefault;
17 import org.eclipse.jdt.annotation.Nullable;
18 import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
19 import org.eclipse.tracecompass.ctf.core.event.types.StructDeclaration;
20 import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
21 import org.eclipse.tracecompass.ctf.parser.CTFParser;
22 import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
23 import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
24 import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.AlignmentParser;
25 import org.eclipse.tracecompass.internal.ctf.core.event.types.StructDeclarationFlattener;
26
27 /**
28 *
29 * Structures are aligned on the largest alignment required by basic types
30 * contained within the structure. (This follows the ISO/C standard for
31 * structures) <br>
32 * TSDL metadata representation of a named structure:
33 *
34 * <pre>
35 struct name {
36 field_type field_name;
37 field_type field_name;
38 // ...
39 };
40 * </pre>
41 *
42 * Example:
43 *
44 * <pre>
45 struct example {
46 integer { // nameless type
47 size = 16;
48 signed = true;
49 align = 16;
50 } first_field_name;
51 uint64_t second_field_name; // named type declared in the metadata
52 };
53 * </pre>
54 *
55 * The fields are placed in a sequence next to each other. They each possess a
56 * field name, which is a unique identifier within the structure. The identifier
57 * is not allowed to use any [reserved keyword](#specC.1.2). Replacing reserved
58 * keywords with underscore-prefixed field names is <strong>recommended</strong>
59 * . Fields starting with an underscore should have their leading underscore
60 * removed by the CTF trace readers. <br>
61 * A nameless structure can be declared as a field type or as part of a
62 * `typedef`:
63 *
64 * <pre>
65 struct {
66 // ...
67 }
68 *
69 * </pre>
70 *
71 * Alignment for a structure compound type can be forced to a minimum value by
72 * adding an `align` specifier after the declaration of a structure body. This
73 * attribute is read as: `align(value)`. The value is specified in bits. The
74 * structure will be aligned on the maximum value between this attribute and the
75 * alignment required by the basic types contained within the structure. e.g.
76 *
77 * <pre>
78 struct {
79 // ...
80 } align(32)
81 }
82 * </pre>
83 *
84 * @author Matthew Khouzam
85 * @author Efficios - Javadoc preamble
86 */
87 public final class StructParser extends AbstractScopedCommonTreeParser {
88
89 /**
90 * Parameter object
91 *
92 * @author Matthew Khouzam
93 *
94 */
95 @NonNullByDefault
96 public static final class Param implements ICommonTreeParserParameter {
97 private final DeclarationScope fDeclarationScope;
98 private final @Nullable CommonTree fIdentifier;
99 private final CTFTrace fTrace;
100
101 /**
102 * Constructor
103 *
104 * @param trace
105 * the trace
106 * @param identifier
107 * the identifier
108 * @param scope
109 * the current scope
110 */
111 public Param(CTFTrace trace, @Nullable CommonTree identifier, DeclarationScope scope) {
112 fTrace = trace;
113 fIdentifier = identifier;
114 fDeclarationScope = scope;
115 }
116 }
117
118 /**
119 * The instance
120 */
121 public static final StructParser INSTANCE = new StructParser();
122
123 private StructParser() {
124 }
125
126 /**
127 * Parse the struct AST node, So everything in "struct a {...};"
128 *
129 * @param struct
130 * the struct AST node
131 * @param param
132 * the parameter object of {@link Param} type.
133 * @return a {@link StructDeclaration} that is fully populated
134 * @throws ParseException
135 * the AST is malformed
136 */
137 @Override
138 public StructDeclaration parse(CommonTree struct, ICommonTreeParserParameter param) throws ParseException {
139 if (!(param instanceof Param)) {
140 throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
141 }
142 final DeclarationScope scope = ((Param) param).fDeclarationScope;
143 CommonTree identifier = ((Param) param).fIdentifier;
144
145 List<CommonTree> children = struct.getChildren();
146
147 /* The return value */
148 StructDeclaration structDeclaration = null;
149
150 /* Name */
151 String structName = null;
152 boolean hasName = false;
153
154 /* Body */
155 CommonTree structBody = null;
156 boolean hasBody = false;
157
158 /* Align */
159 long structAlign = 0;
160
161 /* Loop on all children and identify what we have to work with. */
162 for (CommonTree child : children) {
163 switch (child.getType()) {
164 case CTFParser.STRUCT_NAME: {
165 hasName = true;
166 CommonTree structNameIdentifier = (CommonTree) child.getChild(0);
167 structName = structNameIdentifier.getText();
168 break;
169 }
170 case CTFParser.STRUCT_BODY: {
171 hasBody = true;
172
173 structBody = child;
174 break;
175 }
176 case CTFParser.ALIGN: {
177 CommonTree structAlignExpression = (CommonTree) child.getChild(0);
178
179 structAlign = AlignmentParser.INSTANCE.parse(structAlignExpression, null);
180 break;
181 }
182 default:
183 throw childTypeError(child);
184 }
185 }
186
187 if (!hasName && identifier != null) {
188 structName = identifier.getText();
189 hasName = true;
190 }
191
192 /*
193 * If a struct has just a body and no name (just like the song,
194 * "A Struct With No Name" by America (sorry for that...)), it's a
195 * definition of a new type, so we create the type declaration and
196 * return it. We can't add it to the declaration scope since there is no
197 * name, but that's what we want because it won't be possible to use it
198 * again to declare another field.
199 *
200 * If it has just a name, we look it up in the declaration scope and
201 * return the associated declaration. If it is not found in the
202 * declaration scope, it means that a struct with that name has not been
203 * declared, which is an error.
204 *
205 * If it has both, then we create the type declaration and register it
206 * to the current scope.
207 *
208 * If it has none, then what are we doing here ?
209 */
210 if (hasBody) {
211 /*
212 * If struct has a name, check if already defined in the current
213 * scope.
214 */
215 if (hasName && (scope.lookupStruct(structName) != null)) {
216 throw new ParseException("struct " + structName //$NON-NLS-1$
217 + " already defined."); //$NON-NLS-1$
218 }
219 /* Create the declaration */
220 structDeclaration = new StructDeclaration(structAlign);
221
222 CTFTrace trace = ((Param) param).fTrace;
223 /* Parse the body */
224 StructBodyParser.INSTANCE.parse(structBody, new StructBodyParser.Param(structDeclaration, trace, structName, scope));
225 /* If struct has name, add it to the current scope. */
226 if (hasName) {
227 scope.registerStruct(structName, structDeclaration);
228 }
229 } else /* !hasBody */ {
230 if (hasName) {
231 /* Name and !body */
232
233 /* Lookup the name in the current scope. */
234 structDeclaration = scope.lookupStructRecursive(structName);
235
236 /*
237 * If not found, it means that a struct with such name has not
238 * been defined
239 */
240 if (structDeclaration == null) {
241 throw new ParseException("struct " + structName //$NON-NLS-1$
242 + " is not defined"); //$NON-NLS-1$
243 }
244 } else {
245 /* !Name and !body */
246
247 /* We can't do anything with that. */
248 throw new ParseException("struct with no name and no body"); //$NON-NLS-1$
249 }
250 }
251 return StructDeclarationFlattener.tryFlattenStruct(structDeclaration);
252 }
253
254 }
This page took 0.035568 seconds and 5 git commands to generate.