Add JVM compiler support.
2 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
6 * The contents of this file are subject to the terms of either the GNU
7 * General Public License Version 2 only ("GPL") or the Common
8 * Development and Distribution License("CDDL") (collectively, the
9 * "License"). You may not use this file except in compliance with the
10 * License. You can obtain a copy of the License at
11 * http://www.netbeans.org/cddl-gplv2.html
12 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13 * specific language governing permissions and limitations under the
14 * License. When distributing the software, include this License Header
15 * Notice in each file and include the License file at
16 * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17 * particular file as subject to the "Classpath" exception as provided
18 * by Sun in the GPL Version 2 section of the License file that
19 * accompanied this code. If applicable, add the following below the
20 * License Header, with the fields enclosed by brackets [] replaced by
21 * your own identifying information:
22 * "Portions Copyrighted [year] [name of copyright owner]"
24 * If you wish your version of this file to be governed by only the CDDL
25 * or only the GPL Version 2, indicate your decision by adding
26 * "[Contributor] elects to include this software in this distribution
27 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28 * single choice of license, a recipient has the option to distribute
29 * your version of this file under either the CDDL, the GPL Version 2 or
30 * to extend the choice of license to its licensees as provided above.
31 * However, if you add GPL Version 2 code and therefore, elected the GPL
32 * Version 2 license, then the option applies only if the new code is
33 * made subject to such option by the copyright holder.
37 * Portions Copyrighted 2008 Sun Microsystems, Inc.
40 package org.netbeans.modules.ada.editor.parser;
42 import java.util.ArrayList;
43 import java.util.Arrays;
44 import java.util.List;
45 import java.util.logging.Level;
46 import java.util.logging.Logger;
47 import java_cup.runtime.Symbol;
48 import org.netbeans.modules.ada.editor.parser.AdaParser.Context;
49 import org.netbeans.modules.ada.editor.ast.ASTError;
50 import org.netbeans.modules.ada.editor.ast.ASTNode;
51 import org.netbeans.modules.ada.editor.ast.nodes.Program;
52 import org.netbeans.modules.csl.api.Severity;
53 import org.openide.util.NbBundle;
54 import org.netbeans.modules.csl.api.Error;
57 * Based on org.netbeans.modules.php.editor.parser.PHP5ErrorHandler
59 * @author Andrea Lucarelli
61 public class Ada95ErrorHandler implements ParserErrorHandler {
63 private static final Logger LOGGER = Logger.getLogger(Ada95ErrorHandler.class.getName());
65 public static class SyntaxError {
66 private final short[] expectedTokens;
67 private final Symbol currentToken;
68 private final Symbol previousToken;
70 public SyntaxError(short[] expectedTokens, Symbol currentToken, Symbol previousToken) {
71 this.expectedTokens = expectedTokens;
72 this.currentToken = currentToken;
73 this.previousToken = previousToken;
76 public Symbol getCurrentToken() {
80 public Symbol getPreviousToken() {
84 public short[] getExpectedTokens() {
85 return expectedTokens;
89 private final List<SyntaxError> syntaxErrors;
91 private final Context context;
94 public Ada95ErrorHandler(Context context, AdaParser outer) {
97 this.context = context;
98 syntaxErrors = new ArrayList<SyntaxError>();
99 //LOGGER.setLevel(Level.FINE);
102 public void handleError(Type type, short[] expectedtokens, Symbol current, Symbol previous) {
104 if (type == ParserErrorHandler.Type.SYNTAX_ERROR) {
105 // logging syntax error
106 if (LOGGER.isLoggable(Level.FINE)) {
107 LOGGER.fine("Syntax error:"); //NOI18N
108 LOGGER.fine("Current [" + current.left + ", " + current.right + "](" + Utils.getASTScannerTokenName(current.sym) + "): " + current.value); //NOI18N
109 LOGGER.fine("Previous [" + previous.left + ", " + previous.right + "] (" + Utils.getASTScannerTokenName(previous.sym) + "):" + previous.value); //NOI18N
110 StringBuffer message = new StringBuffer();
111 message.append("Expected tokens:"); //NOI18N
112 for (int i = 0; i < expectedtokens.length; i += 2) {
113 message.append(" ").append( Utils.getASTScannerTokenName(expectedtokens[i])); //NOI18N
115 LOGGER.fine(message.toString());
117 syntaxErrors.add(new SyntaxError(expectedtokens, current, previous));
119 String message = null;
120 if (current != null) {
121 String tagText = getTokenTextForm(current.sym);
122 if (tagText != null) {
123 message = NbBundle.getMessage(Ada95ErrorHandler.class, "SE_Unexpected") + " " + tagText;
126 message = NbBundle.getMessage(Ada95ErrorHandler.class, "SE_Unexpected") + " " + Utils.getASTScannerTokenName(current.sym);
129 if (message == null) {
130 message = "Parser error"; // NOI18N
132 error = new AdaError(message, context.getSnapshot().getSource().getFileObject(), current.left, current.right, Severity.ERROR, null);
133 //context.getListener().error(error);
137 public void handleError(Type type, Symbol symbol, String message) {
139 if (symbol != null) {
140 if (message == null) {
141 message = "Parser error";
143 error = new AdaError(message, context.getSnapshot().getSource().getFileObject(), symbol.left, symbol.right, Severity.ERROR, null);
144 //TODO: context.getListener().error(error);
148 public List<Error> displayFatalError(){
149 Error error = new FatalError();
150 return Arrays.asList(error);
153 public List<Error> displaySyntaxErrors(Program program) {
154 List<Error> errors = new ArrayList<Error>();
155 for (SyntaxError syntaxError : syntaxErrors) {
156 ASTNode astError = null;
157 if (program != null) {
158 astError = org.netbeans.modules.ada.editor.ast.ASTUtils.getNodeAtOffset(program, syntaxError.currentToken.left);
159 if (!(astError instanceof ASTError)) {
160 astError = org.netbeans.modules.ada.editor.ast.ASTUtils.getNodeAtOffset(program, syntaxError.previousToken.right);
161 if (!(astError instanceof ASTError)) {
165 if (astError != null) {
166 LOGGER.fine("ASTError [" + astError.getStartOffset() + ", " + astError.getEndOffset() + "]"); //NOI18N
168 LOGGER.fine("ASTError was not found"); //NOI18N
171 Error error = defaultSyntaxErrorHandling(syntaxError, astError);
177 // This is just defualt handling. We can do a logic, which will find metter
178 private Error defaultSyntaxErrorHandling(SyntaxError syntaxError, ASTNode astError) {
180 String unexpectedText = ""; //NOI18N
181 StringBuffer message = new StringBuffer();
182 boolean isUnexpected = false;
183 int start = syntaxError.getCurrentToken().left;
184 int end = syntaxError.getCurrentToken().right;
186 if (syntaxError.getCurrentToken().sym == Ada95ASTSymbols.EOF) {
188 unexpectedText = NbBundle.getMessage(Ada95ErrorHandler.class, "SE_EOF");
192 String currentText = (String)syntaxError.getCurrentToken().value;
193 isUnexpected = currentText != null && currentText.trim().length() > 0;
195 unexpectedText = currentText.trim();
196 end = start + unexpectedText.length();
200 List<String> possibleTags = new ArrayList<String>();
201 for (int i = 0; i < syntaxError.getExpectedTokens().length; i += 2) {
202 String text = getTokenTextForm(syntaxError.getExpectedTokens()[i]);
204 possibleTags.add(text);
208 message.append(NbBundle.getMessage(Ada95ErrorHandler.class, "SE_Message"));
209 message.append(':'); //NOI18N
211 message.append(' ').append(NbBundle.getMessage(Ada95ErrorHandler.class, "SE_Unexpected"));
212 message.append(": "); //NOI18N
213 message.append(unexpectedText);
215 if (possibleTags.size() > 0) {
216 message.append('\n').append(NbBundle.getMessage(Ada95ErrorHandler.class, "SE_Expected"));
217 message.append(": "); //NOI18N
218 boolean addOR = false;
219 for (String tag : possibleTags) {
221 message.append(" " + NbBundle.getMessage(Ada95ErrorHandler.class, "SE_Or") + " ");
231 if (astError != null){
232 start = astError.getStartOffset();
233 end = astError.getEndOffset();
234 // if the asterror is trough two lines, the problem is ussually at the end
235 String text = context.getSource().substring(start, end);
236 int lastNewLine = text.length()-1;
237 while (text.charAt(lastNewLine) == '\n' || text.charAt(lastNewLine) == '\r'
238 || text.charAt(lastNewLine) == '\t' || text.charAt(lastNewLine) == ' ') {
240 if (lastNewLine < 0) {
244 lastNewLine = text.lastIndexOf('\n', lastNewLine); //NOI18N
245 if (lastNewLine > 0) {
246 start = start + lastNewLine + 1;
249 error = new AdaError(message.toString(), context.getSnapshot().getSource().getFileObject(), start, end, Severity.ERROR, new Object[]{syntaxError});
253 public List<SyntaxError> getSyntaxErrors() {
257 private String getTokenTextForm (int token) {
260 case Ada95ASTSymbols.BASED_LITERAL : text = "number"; break; //NOI18N
261 case Ada95ASTSymbols.DECIMAL_LITERAL : text = "number"; break; //NOI18N
262 case Ada95ASTSymbols.IDENTIFIER : text = "identifier"; break; //NOI18N
263 case Ada95ASTSymbols.ABORT : text = "abort"; break; //NOI18N
264 case Ada95ASTSymbols.ABS : text = "abs"; break; //NOI18N
265 case Ada95ASTSymbols.ABSTRACT : text = "abstract"; break; //NOI18N
266 case Ada95ASTSymbols.ACCESS : text = "access"; break; //NOI18N
267 case Ada95ASTSymbols.ACCEPT : text = "access"; break; //NOI18N
268 case Ada95ASTSymbols.ALIASED : text = "aliased"; break; //NOI18N
269 case Ada95ASTSymbols.ALL : text = "all"; break; //NOI18N
270 case Ada95ASTSymbols.AND : text = "and"; break; //NOI18N
271 case Ada95ASTSymbols.ARRAY : text = "array"; break; //NOI18N
272 case Ada95ASTSymbols.AT : text = "at"; break; //NOI18N
273 case Ada95ASTSymbols.BEGIN : text = "begin"; break; //NOI18N
274 case Ada95ASTSymbols.BODY : text = "body"; break; //NOI18N
275 case Ada95ASTSymbols.CONSTANT : text = "constant"; break; //NOI18N
276 case Ada95ASTSymbols.CASE : text = "case"; break; //NOI18N
277 case Ada95ASTSymbols.DECLARE : text = "declare"; break; //NOI18N
278 case Ada95ASTSymbols.DELAY : text = "delay"; break; //NOI18N
279 case Ada95ASTSymbols.DELTA : text = "delta"; break; //NOI18N
280 case Ada95ASTSymbols.DIGITS : text = "digits"; break; //NOI18N
281 case Ada95ASTSymbols.DO : text = "do"; break; //NOI18N
282 case Ada95ASTSymbols.ELSE : text = "else"; break; //NOI18N
283 case Ada95ASTSymbols.ELSIF : text = "elsif"; break; //NOI18N
284 case Ada95ASTSymbols.END : text = "end"; break; //NOI18N
285 case Ada95ASTSymbols.ENTRY : text = "entry"; break; //NOI18N
286 case Ada95ASTSymbols.EXCEPTION : text = "exception"; break; //NOI18N
287 case Ada95ASTSymbols.EXIT : text = "exit"; break; //NOI18N
288 case Ada95ASTSymbols.FOR : text = "for"; break; //NOI18N
289 case Ada95ASTSymbols.FUNCTION : text = "function"; break; //NOI18N
290 case Ada95ASTSymbols.GENERIC : text = "generic"; break; //NOI18N
291 case Ada95ASTSymbols.GOTO : text = "goto"; break; //NOI18N
292 case Ada95ASTSymbols.IF : text = "if"; break; //NOI18N
293 case Ada95ASTSymbols.IN : text = "in"; break; //NOI18N
294 case Ada95ASTSymbols.IS : text = "is"; break; //NOI18N
295 case Ada95ASTSymbols.LIMITED : text = "limited"; break; //NOI18N
296 case Ada95ASTSymbols.LOOP : text = "loop"; break; //NOI18N
297 case Ada95ASTSymbols.MOD : text = "mod"; break; //NOI18N
298 case Ada95ASTSymbols.NEW : text = "new"; break; //NOI18N
299 case Ada95ASTSymbols.NOT : text = "not"; break; //NOI18N
300 case Ada95ASTSymbols.NULL : text = "null"; break; //NOI18N
301 case Ada95ASTSymbols.OF : text = "of"; break; //NOI18N
302 case Ada95ASTSymbols.OR : text = "or"; break; //NOI18N
303 case Ada95ASTSymbols.OTHERS : text = "others"; break; //NOI18N
304 case Ada95ASTSymbols.OUT : text = "out"; break; //NOI18N
305 case Ada95ASTSymbols.PACKAGE : text = "package"; break; //NOI18N
306 case Ada95ASTSymbols.PRAGMA : text = "pragma"; break; //NOI18N
307 case Ada95ASTSymbols.PRIVATE : text = "private"; break; //NOI18N
308 case Ada95ASTSymbols.PROCEDURE : text = "procedure"; break; //NOI18N
309 case Ada95ASTSymbols.PROTECTED : text = "protected"; break; //NOI18N
310 case Ada95ASTSymbols.RETURN : text = "return"; break; //NOI18N
311 case Ada95ASTSymbols.REVERSE : text = "reverse"; break; //NOI18N
312 case Ada95ASTSymbols.RAISE : text = "raise"; break; //NOI18N
313 case Ada95ASTSymbols.RANGE : text = "range"; break; //NOI18N
314 case Ada95ASTSymbols.RECORD : text = "record"; break; //NOI18N
315 case Ada95ASTSymbols.REM : text = "rem"; break; //NOI18N
316 case Ada95ASTSymbols.RENAMES : text = "renames"; break; //NOI18N
317 case Ada95ASTSymbols.REQUEUE : text = "requeue"; break; //NOI18N
318 case Ada95ASTSymbols.SELECT : text = "select"; break; //NOI18N
319 case Ada95ASTSymbols.SEPARATE : text = "separate"; break; //NOI18N
320 case Ada95ASTSymbols.SUBTYPE : text = "subtype"; break; //NOI18N
321 case Ada95ASTSymbols.TAGGED : text = "tagged"; break; //NOI18N
322 case Ada95ASTSymbols.TASK : text = "task"; break; //NOI18N
323 case Ada95ASTSymbols.TERMINATE : text = "terminate"; break; //NOI18N
324 case Ada95ASTSymbols.THEN : text = "then"; break; //NOI18N
325 case Ada95ASTSymbols.TYPE : text = "type"; break; //NOI18N
326 case Ada95ASTSymbols.UNTIL : text = "until"; break; //NOI18N
327 case Ada95ASTSymbols.USE : text = "use"; break; //NOI18N
328 case Ada95ASTSymbols.WHEN : text = "when"; break; //NOI18N
329 case Ada95ASTSymbols.WHILE : text = "while"; break; //NOI18N
330 case Ada95ASTSymbols.WITH : text = "with"; break; //NOI18N
331 case Ada95ASTSymbols.XOR : text = "xor"; break; //NOI18N
332 case Ada95ASTSymbols.AMP : text = "&"; break; //NOI18N
333 case Ada95ASTSymbols.TICK : text = "'"; break; //NOI18N
334 case Ada95ASTSymbols.LPAREN : text = "("; break; //NOI18N
335 case Ada95ASTSymbols.RPAREN : text = ")"; break; //NOI18N
336 case Ada95ASTSymbols.STAR : text = "*"; break; //NOI18N
337 case Ada95ASTSymbols.PLUS : text = "+"; break; //NOI18N
338 case Ada95ASTSymbols.COMMA : text = ","; break; //NOI18N
339 case Ada95ASTSymbols.MINUS : text = "-"; break; //NOI18N
340 case Ada95ASTSymbols.DOT : text = "."; break; //NOI18N
341 case Ada95ASTSymbols.SLASH : text = "/"; break; //NOI18N
342 case Ada95ASTSymbols.COLON : text = ":"; break; //NOI18N
343 case Ada95ASTSymbols.SEMICOLON : text = ";"; break; //NOI18N
344 case Ada95ASTSymbols.GT : text = "<"; break; //NOI18N
345 case Ada95ASTSymbols.EQ : text = "="; break; //NOI18N
346 case Ada95ASTSymbols.LT : text = ">"; break; //NOI18N
347 case Ada95ASTSymbols.BAR : text = "|"; break; //NOI18N
348 case Ada95ASTSymbols.ARROW : text = "=>"; break; //NOI18N
349 case Ada95ASTSymbols.DOT_DOT : text = ".."; break; //NOI18N
350 case Ada95ASTSymbols.EXPON : text = "**"; break; //NOI18N
351 case Ada95ASTSymbols.ASSIGNMENT : text = ":="; break; //NOI18N
352 case Ada95ASTSymbols.INEQ : text = "/="; break; //NOI18N
353 case Ada95ASTSymbols.GTEQ : text = ">="; break; //NOI18N
354 case Ada95ASTSymbols.LTEQ : text = "<="; break; //NOI18N
355 case Ada95ASTSymbols.LTLT : text = "<<"; break; //NOI18N
356 case Ada95ASTSymbols.GTGT : text = ">>"; break; //NOI18N
357 case Ada95ASTSymbols.BOX : text = "<>"; break; //NOI18N
362 private class FatalError extends AdaError{
364 super(NbBundle.getMessage(Ada95ErrorHandler.class, "MSG_FatalError"),
365 context.getSnapshot().getSource().getFileObject(),
366 0, context.getSource().length(),
367 Severity.ERROR, null);
371 public boolean isLineError() {