ctf: make all parser implementations final classes
[deliverable/tracecompass.git] / ctf / org.eclipse.tracecompass.ctf.core / src / org / eclipse / tracecompass / internal / ctf / core / event / metadata / tsdl / TypeDeclaratorParser.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;
10
11 import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.childTypeError;
12 import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.concatenateUnaryStrings;
13 import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isAnyUnaryString;
14 import static org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.TsdlUtils.isUnaryInteger;
15
16 import java.util.Collections;
17 import java.util.LinkedList;
18 import java.util.List;
19
20 import org.antlr.runtime.tree.CommonTree;
21 import org.eclipse.jdt.annotation.NonNull;
22 import org.eclipse.jdt.annotation.NonNullByDefault;
23 import org.eclipse.tracecompass.ctf.core.event.metadata.DeclarationScope;
24 import org.eclipse.tracecompass.ctf.core.event.types.IDeclaration;
25 import org.eclipse.tracecompass.ctf.core.event.types.IntegerDeclaration;
26 import org.eclipse.tracecompass.ctf.core.trace.CTFTrace;
27 import org.eclipse.tracecompass.ctf.parser.CTFParser;
28 import org.eclipse.tracecompass.internal.ctf.core.event.metadata.AbstractScopedCommonTreeParser;
29 import org.eclipse.tracecompass.internal.ctf.core.event.metadata.ParseException;
30 import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.event.EventScopeParser;
31 import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.stream.StreamScopeParser;
32 import org.eclipse.tracecompass.internal.ctf.core.event.metadata.tsdl.trace.TraceScopeParser;
33 import org.eclipse.tracecompass.internal.ctf.core.event.types.ArrayDeclaration;
34 import org.eclipse.tracecompass.internal.ctf.core.event.types.SequenceDeclaration;
35
36 /**
37 * A type declarator parser
38 *
39 * @author Matthew Khouzam
40 *
41 */
42 public final class TypeDeclaratorParser extends AbstractScopedCommonTreeParser {
43
44 /**
45 * The parameter object for type declarator parsers
46 *
47 * @author Matthew Khouzam
48 *
49 */
50 @NonNullByDefault
51 public static final class Param implements ICommonTreeParserParameter {
52 private final DeclarationScope fDeclarationScope;
53 private final CommonTree fListNode;
54 private final StringBuilder fBuilder;
55 private final CTFTrace fTrace;
56
57 /**
58 * Parameter constructor
59 *
60 * @param trace
61 * the trace
62 * @param listNode
63 * the listNode
64 * @param scope
65 * the scope
66 * @param builder
67 * the string builder to populate
68 */
69 public Param(CTFTrace trace, CommonTree listNode, DeclarationScope scope, StringBuilder builder) {
70 fTrace = trace;
71 fListNode = listNode;
72 fDeclarationScope = scope;
73 fBuilder = builder;
74 }
75 }
76
77 /**
78 * The instance
79 */
80 public final static TypeDeclaratorParser INSTANCE = new TypeDeclaratorParser();
81
82 private TypeDeclaratorParser() {
83 }
84
85 /**
86 * Parses a pair type declarator / type specifier list and returns the
87 * corresponding declaration. If it is present, it also writes the
88 * identifier of the declarator in the given {@link StringBuilder}.
89 *
90 * @param typeDeclarator
91 * A TYPE_DECLARATOR node.
92 * @param param
93 * the parameter object
94 * @return The corresponding declaration.
95 * @throws ParseException
96 * If there is an error finding or creating the declaration.
97 */
98 @Override
99 public IDeclaration parse(CommonTree typeDeclarator, ICommonTreeParserParameter param) throws ParseException {
100 if (!(param instanceof Param)) {
101 throw new IllegalArgumentException("Param must be a " + Param.class.getCanonicalName()); //$NON-NLS-1$
102 }
103 DeclarationScope scope = ((Param) param).fDeclarationScope;
104 CTFTrace trace = ((Param) param).fTrace;
105 CommonTree typeSpecifierList = ((Param) param).fListNode;
106
107 IDeclaration declaration = null;
108 List<CommonTree> children = null;
109 List<@NonNull CommonTree> pointers = new LinkedList<>();
110 List<CommonTree> lengths = new LinkedList<>();
111 CommonTree identifier = null;
112
113 /* Separate the tokens by type */
114 if (typeDeclarator != null) {
115 children = typeDeclarator.getChildren();
116 for (CommonTree child : children) {
117
118 switch (child.getType()) {
119 case CTFParser.POINTER:
120 pointers.add(child);
121 break;
122 case CTFParser.IDENTIFIER:
123 identifier = child;
124 break;
125 case CTFParser.LENGTH:
126 lengths.add(child);
127 break;
128 default:
129 throw childTypeError(child);
130 }
131 }
132
133 }
134
135 /*
136 * Parse the type specifier list, which is the "base" type. For example,
137 * it would be int in int a[3][len].
138 */
139 declaration = TypeSpecifierListParser.INSTANCE.parse(typeSpecifierList, new TypeSpecifierListParser.Param(trace, pointers, identifier, scope));
140
141 /*
142 * Each length subscript means that we must create a nested array or
143 * sequence. For example, int a[3][len] means that we have an array of 3
144 * (sequences of length 'len' of (int)).
145 */
146 if (!lengths.isEmpty()) {
147 /* We begin at the end */
148 Collections.reverse(lengths);
149
150 for (CommonTree length : lengths) {
151 /*
152 * By looking at the first expression, we can determine whether
153 * it is an array or a sequence.
154 */
155 List<CommonTree> lengthChildren = length.getChildren();
156
157 CommonTree first = lengthChildren.get(0);
158 if (isUnaryInteger(first)) {
159 /* Array */
160 int arrayLength = UnaryIntegerParser.INSTANCE.parse(first, null).intValue();
161
162 if (arrayLength < 1) {
163 throw new ParseException("Array length is negative"); //$NON-NLS-1$
164 }
165
166 /* Create the array declaration. */
167 declaration = new ArrayDeclaration(arrayLength, declaration);
168 } else if (isAnyUnaryString(first)) {
169 /* Sequence */
170 String lengthName = concatenateUnaryStrings(lengthChildren);
171
172 /* check that lengthName was declared */
173 if (isSignedIntegerField(lengthName, scope)) {
174 throw new ParseException("Sequence declared with length that is not an unsigned integer"); //$NON-NLS-1$
175 }
176 /* Create the sequence declaration. */
177 declaration = new SequenceDeclaration(lengthName,
178 declaration);
179 } else if (isTrace(first)) {
180 /* Sequence */
181 String lengthName = TraceScopeParser.INSTANCE.parse(null, new TraceScopeParser.Param(lengthChildren));
182
183 /* check that lengthName was declared */
184 if (isSignedIntegerField(lengthName, scope)) {
185 throw new ParseException("Sequence declared with length that is not an unsigned integer"); //$NON-NLS-1$
186 }
187 /* Create the sequence declaration. */
188 declaration = new SequenceDeclaration(lengthName,
189 declaration);
190
191 } else if (isStream(first)) {
192 /* Sequence */
193 String lengthName = StreamScopeParser.INSTANCE.parse(null, new StreamScopeParser.Param(lengthChildren));
194
195 /* check that lengthName was declared */
196 if (isSignedIntegerField(lengthName, scope)) {
197 throw new ParseException("Sequence declared with length that is not an unsigned integer"); //$NON-NLS-1$
198 }
199 /* Create the sequence declaration. */
200 declaration = new SequenceDeclaration(lengthName,
201 declaration);
202 } else if (isEvent(first)) {
203 /* Sequence */
204 String lengthName = EventScopeParser.INSTANCE.parse(null, new EventScopeParser.Param(lengthChildren));
205
206 /* check that lengthName was declared */
207 if (isSignedIntegerField(lengthName, scope)) {
208 throw new ParseException("Sequence declared with length that is not an unsigned integer"); //$NON-NLS-1$
209 }
210 /* Create the sequence declaration. */
211 declaration = new SequenceDeclaration(lengthName,
212 declaration);
213 } else {
214 throw childTypeError(first);
215 }
216 }
217 }
218
219 if (identifier != null) {
220 final String text = identifier.getText();
221 if (text == null) {
222 throw new ParseException("Cannot have unidentified declarator"); //$NON-NLS-1$
223 }
224 ((Param) param).fBuilder.append(text);
225 registerType(declaration, text, scope);
226 }
227
228 return declaration;
229 }
230
231 private static boolean isSignedIntegerField(String lengthName, DeclarationScope scope) throws ParseException {
232 IDeclaration decl = scope.lookupIdentifierRecursive(lengthName);
233 if (decl instanceof IntegerDeclaration) {
234 return ((IntegerDeclaration) decl).isSigned();
235 }
236 throw new ParseException("Is not an integer: " + lengthName); //$NON-NLS-1$
237
238 }
239
240 private static boolean isEvent(CommonTree first) {
241 return first.getType() == CTFParser.EVENT;
242 }
243
244 private static boolean isStream(CommonTree first) {
245 return first.getType() == CTFParser.STREAM;
246 }
247
248 private static boolean isTrace(CommonTree first) {
249 return first.getType() == CTFParser.TRACE;
250 }
251
252 }
This page took 0.049901 seconds and 5 git commands to generate.