testdev/ite/src/com.nokia.testfw.stf.scripteditor/src/com/nokia/testfw/stf/scripteditor/utils/ScriptParser.java
changeset 1 96906a986c3b
equal deleted inserted replaced
0:f1112f777ce9 1:96906a986c3b
       
     1 /*
       
     2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 package com.nokia.testfw.stf.scripteditor.utils;
       
    20 
       
    21 import java.io.BufferedReader;
       
    22 import java.io.StringReader;
       
    23 import java.util.ArrayList;
       
    24 import java.util.List;
       
    25 import java.util.Stack;
       
    26 import java.util.StringTokenizer;
       
    27 
       
    28 import org.eclipse.core.resources.IMarker;
       
    29 import org.eclipse.core.resources.IResource;
       
    30 import org.eclipse.core.resources.ResourcesPlugin;
       
    31 import org.eclipse.core.runtime.CoreException;
       
    32 import org.eclipse.ui.IEditorInput;
       
    33 
       
    34 import com.nokia.testfw.stf.scripteditor.utils.ParseProblem.ProblemType;
       
    35 
       
    36 
       
    37 import java.io.IOException;
       
    38 
       
    39 /**
       
    40  * Parser of script. Used to check syntax and find code sections in cfg files  
       
    41  *
       
    42  */
       
    43 public class ScriptParser {
       
    44 	
       
    45 	/**
       
    46 	 * Default constructor
       
    47 	 *
       
    48 	 */
       
    49 	public ScriptParser() {
       
    50 		problemsList = new ArrayList<ParseProblem>();
       
    51 		markersList = new ArrayList<IMarker>();
       
    52 		createdObjectsList = new ArrayList<String[]>();
       
    53 		
       
    54 	}
       
    55 
       
    56 	/**
       
    57 	 * Removes all problem markers
       
    58 	 *
       
    59 	 */
       
    60 	private void clearProblemMarkers() {
       
    61 		for (int a = 0; a < markersList.size(); a++) {
       
    62 			try {
       
    63 				markersList.get(a).delete();
       
    64 				markersList.remove(a);
       
    65 				
       
    66 			} catch (CoreException ex) {
       
    67 			}
       
    68 		}
       
    69 	}
       
    70 	public void checkScripterScript(String scriptContent, IEditorInput input) {
       
    71 
       
    72 		Parser parser = new Parser("/scripter.xml");
       
    73 		checkScript(scriptContent, input, parser);
       
    74 	}
       
    75 //	public void checkCombinerScript(String scriptContent, IEditorInput input) {
       
    76 //
       
    77 //		Parser parser = new Parser("/combiner.xml");
       
    78 //		checkScript(scriptContent, input, parser);
       
    79 //	
       
    80 //	}
       
    81 	
       
    82 	/**
       
    83 	 * Processes the scriptContent in search of syntax errors (testscripter).
       
    84 	 * The found errors are stored to problemsList.
       
    85 	 * 
       
    86 	 * @param scriptContent
       
    87 	 * 			Content of script as a string
       
    88 	 * @param input
       
    89 	 * 			IEditorInput object needed to display found errors 
       
    90 	 */
       
    91 	public void checkScript(String scriptContent, IEditorInput input, Parser parser) {
       
    92 		Parser.createdMacrosList.clear();
       
    93 		Parser.createdObjectsList.clear();
       
    94 		BufferedReader scriptReader = new BufferedReader(new StringReader(
       
    95 				scriptContent));
       
    96 		String line = null;
       
    97 		lineNumber = -1;
       
    98 		createdObjectsList.clear();
       
    99 		ArrayList<String> commands = parser.provideCommands();
       
   100 		String[] sectionTags = parser.provideSectionTags();
       
   101 		problemsList = new ArrayList<ParseProblem>();
       
   102 		boolean defineSectionFound = false;
       
   103 		// Variables help to remove block comments.
       
   104 		boolean inBlkComment = false;
       
   105 		String token = null;
       
   106 		String token1 = null;
       
   107 		StringTokenizer t = null;
       
   108 		int blkCommentBeginLineNo = -1;
       
   109 		SectionContextStack sectionStack = new SectionContextStack();
       
   110 		SectionContext curSection = null;
       
   111 		subSectionContent = new ArrayList<String>();
       
   112 		
       
   113 		try {
       
   114 			while (true) {
       
   115 				line = scriptReader.readLine();
       
   116 				lineNumber++;
       
   117 
       
   118 				if (line == null) {
       
   119 					break;
       
   120 				}
       
   121 				line = line.trim();
       
   122 				
       
   123 				// Remove block comment enclosed in "/*" and "*/".
       
   124 				// "/*" must be at the begin of the line and "*/ must be at the
       
   125 				// end of the line.
       
   126 				inBlkComment = false;
       
   127 				t = new StringTokenizer(line);
       
   128 				while (t.hasMoreTokens())
       
   129 				{
       
   130 					token = t.nextToken();
       
   131 					if (token.indexOf("/*") >= 0){
       
   132 						if (blkCommentBeginLineNo == -1) {
       
   133 							blkCommentBeginLineNo = lineNumber;
       
   134 						} else {
       
   135 							problemsList.add(new ParseProblem(ProblemType.ERROR, lineNumber,
       
   136 									errorEmbeddedSlashStar));
       
   137 						}
       
   138 					}else if (token.indexOf("*/") >= 0) {
       
   139 						inBlkComment = true; // needed to skip the line containing "*/"
       
   140 						if (blkCommentBeginLineNo != -1) {
       
   141 							blkCommentBeginLineNo = -1;
       
   142 						} else {
       
   143 							problemsList.add(new ParseProblem(ProblemType.ERROR, lineNumber,
       
   144 									errorTailStarSlash));
       
   145 						}
       
   146 					}
       
   147 				}
       
   148 				
       
   149 				if (line.indexOf("/*") > 0) {
       
   150 					problemsList.add(new ParseProblem(ProblemType.ERROR, lineNumber,
       
   151 							errorSlashStarMustBeFirstWord));
       
   152 				}
       
   153 				
       
   154 				if (line.indexOf("*/") > 0 && !line.substring(line.length() - 2).equals("*/")) {
       
   155 					problemsList.add(new ParseProblem(ProblemType.ERROR, lineNumber,
       
   156 							errorStarSlashMustBeLastWord));
       
   157 				}
       
   158 
       
   159 				if (blkCommentBeginLineNo != -1 || inBlkComment || line.equals("") || line.startsWith("//") || line.startsWith("#")){
       
   160 					if (sectionStack.lastSectionContext() != null) {
       
   161 						sectionStack.lastSectionContext().incTitleAtLine();
       
   162 					}
       
   163 					continue;
       
   164 				}
       
   165 				
       
   166 				// removes line comments
       
   167 				String[] commentsRem = line.split("//");
       
   168 				if(commentsRem.length > 0){
       
   169 				line = commentsRem[0].trim();
       
   170 				}
       
   171 				
       
   172 				if (line.startsWith("[")) {
       
   173 					// Section tag found
       
   174 					t = new StringTokenizer(line);
       
   175 					while (t.hasMoreTokens()) // Tags can be located at one line.
       
   176 					{
       
   177 						if(t.countTokens()>1){
       
   178 							token = t.nextToken();
       
   179 							token1 = t.nextToken();
       
   180 							if(token1!=null){
       
   181 								if(token.equals("[Sub") && !subSectionContent.contains("[Sub")){
       
   182 									subSectionContent.add(token);
       
   183 								}
       
   184 								if(token1.matches("([a-z]+)\\]")){
       
   185 									subSectionContent.add(token1);
       
   186 								}
       
   187 							}
       
   188 						}
       
   189 						else
       
   190 							token = t.nextToken();
       
   191 						
       
   192 						if(token.equals("[Sub]")){
       
   193 							// Non-existing tag
       
   194 							problemsList.add(new ParseProblem(ProblemType.ERROR, lineNumber,
       
   195 									errorSubTagMissingTitle + token + "\""));
       
   196 						}
       
   197 						
       
   198 						if(token.equals("[Sub")){
       
   199 							token = "[Sub]";
       
   200 						}
       
   201 
       
   202 						int i = findSectionTagIndex(sectionTags, token);
       
   203 						if (i < sectionTags.length) {
       
   204 							if (i % 2 == 0) { // Section opened.
       
   205 								if (sectionStack.size() > 0) {
       
   206 									problemsList.add(new ParseProblem(ProblemType.ERROR, lineNumber,
       
   207 											errorEmbeddedSection));
       
   208 									curSection = sectionStack.lastSectionContext();
       
   209 								}
       
   210 								sectionStack.addContext(new SectionContext(i, lineNumber, sectionTags[i].equals("[Test]")));
       
   211 
       
   212 								// Mandatory "title" keyword right after [Test]
       
   213 								// tag.
       
   214 								if (sectionStack.lastSectionContext().isTestSection) {
       
   215 									sectionStack.lastSectionContext().setTitleAtLine(lineNumber + 1);
       
   216 									sectionStack.lastSectionContext().setTitleExpected(true);
       
   217 								}
       
   218 							} else { // Section closed
       
   219 								curSection = sectionStack.lastSectionContext();
       
   220 								if (sectionTags[i].equals("[Endtest]") && curSection != null
       
   221 										&& curSection.isTestSection && curSection.isTitleExpected()) {
       
   222 									problemsList.add(new ParseProblem(ProblemType.ERROR, curSection.getTitleAtLine(),
       
   223 											errorTitleMustBeTheFirstWord));
       
   224 								}
       
   225 								if (!sectionStack.removeContext(i)) { 
       
   226 									// Cannot find nearest paired open section tag.
       
   227 									problemsList.add(new ParseProblem(ProblemType.ERROR, lineNumber,
       
   228 													errorMissingTag + sectionTags[i - 1] + doubleQuotation));
       
   229 								}
       
   230 							}
       
   231 						} else {
       
   232 							// Non-existing tag
       
   233 							problemsList.add(new ParseProblem(ProblemType.ERROR, lineNumber,
       
   234 									errorNonExistingTag + token + doubleQuotation));
       
   235 						}
       
   236 					}
       
   237 				} else { // Commands.
       
   238 					ArrayList<String> tokenizedLine = lineTokenize(line);
       
   239 					// "title" must be the first word.
       
   240 					ArrayList<String> tLine = lineTokenize(line);
       
   241 					curSection = sectionStack.lastSectionContext();
       
   242 					if (tLine.size() > 0 && tLine.get(0).equals("title")) {
       
   243 						if (curSection != null){
       
   244 							if (!curSection.isTitleExpected()) { // Multiple title lines detected.
       
   245 								problemsList.add(new ParseProblem(ProblemType.ERROR, lineNumber,
       
   246 										errorUnexpectedTitle));
       
   247 							} else	if (curSection.getTitleAtLine()!= lineNumber) { // title line at wrong line.
       
   248 								problemsList.add(new ParseProblem(ProblemType.ERROR, lineNumber,
       
   249 										errorTitleMustBeTheFirstWord));
       
   250 							} else {
       
   251 								curSection.setTitleExpected(false);
       
   252 								continue;
       
   253 							}
       
   254 						}
       
   255 					}
       
   256 
       
   257 					checkCreatedObjects(tokenizedLine);
       
   258 
       
   259 					String command = null;
       
   260 					if (tokenizedLine.size() > 0) {
       
   261 						command = tokenizedLine.get(0);
       
   262 					}
       
   263 					tokenizedLine = resolveDefine(tokenizedLine);
       
   264 					String lineCheck = checkCommand(commands, tokenizedLine, parser);
       
   265 					int defIndex = findSectionTagIndex(sectionTags, "[Define]");
       
   266 					int inclIndex = findSectionTagIndex(sectionTags, "[New_Include_Module]");
       
   267 					defineSectionFound = sectionStack .isCurrentSection(defIndex)
       
   268 							|| sectionStack.isCurrentSection(inclIndex);
       
   269 
       
   270 					if (defineSectionFound) {
       
   271 						// Inside a define section
       
   272 						if (tokenizedLine.size() == 0) {
       
   273 							continue;
       
   274 						}
       
   275 
       
   276 						// check if statement in define section have 2
       
   277 						// elements (e.g. "EVENT TestScripterEvent")
       
   278 						if (tokenizedLine.size() != 2) {
       
   279 							problemsList.add(new ParseProblem(ProblemType.ERROR, lineNumber,
       
   280 									errorSyntaxError));
       
   281 						} else {
       
   282 							// if statement contains keyword it can't be
       
   283 							// used in define section.
       
   284 							for (int i = 0; i < commands.size(); i++) {
       
   285 								if (command.equals(commands.get(i))) {
       
   286 									problemsList.add(new ParseProblem(ProblemType.ERROR, lineNumber,
       
   287 											errorSyntaxError));
       
   288 								}
       
   289 							}
       
   290 							makeDefineObjects(tokenizedLine);
       
   291 						}
       
   292 					}
       
   293 					// if line do not contains valid command with valid
       
   294 					// parameters error note is displayed
       
   295 					if (sectionStack.size() > 0) {
       
   296 						// Command inside section
       
   297 						if (command != null && command.equals("INCLUDE")) {
       
   298 							// INCLUDE not expected.
       
   299 							problemsList.add(new ParseProblem(ProblemType.ERROR, lineNumber, errorNonSectionCmd + command + doubleQuotation));
       
   300 						}
       
   301 					} else {
       
   302 						// Command outside section
       
   303 						if (command != null && !command.equals("INCLUDE")) {
       
   304 							// free text detected.
       
   305 							problemsList.add(new ParseProblem(ProblemType.ERROR, lineNumber, errorFreeText));
       
   306 						} else if (lineCheck != null) {
       
   307 							// INCLUDE syntax error
       
   308 							problemsList.add(new ParseProblem(ProblemType.ERROR, lineNumber, lineCheck));
       
   309 						}
       
   310 					}
       
   311 				}
       
   312 			}
       
   313 			
       
   314 			if (blkCommentBeginLineNo != -1){
       
   315 				problemsList.add(new ParseProblem(ProblemType.ERROR, blkCommentBeginLineNo,
       
   316 						errorMissingStarSlash));
       
   317 			}
       
   318 			// check if all sections are closed.
       
   319 			SectionContext[] arr = new SectionContext[sectionStack.size()];
       
   320 			sectionStack.toArray(arr);
       
   321 			for (SectionContext tmp : arr) {
       
   322 				problemsList.add(new ParseProblem(ProblemType.ERROR, tmp.lineNumber, errorMissingTag + sectionTags[tmp.sectionIndex + 1] + "\""));
       
   323 				if (tmp.isTestSection && tmp.isTitleExpected()) {
       
   324 					problemsList.add(new ParseProblem(ProblemType.ERROR, tmp.getTitleAtLine(),
       
   325 					errorTitleMustBeTheFirstWord));
       
   326 				}
       
   327 			}
       
   328 		} catch (IOException ex) {
       
   329 
       
   330 		}
       
   331 		addErrorMarkers(input);
       
   332 	}
       
   333 	
       
   334 	/**
       
   335 	 * checks if line starts with created object, if so no error would be displayed
       
   336 	 * 
       
   337 	 * @param tokenizedLine
       
   338 	 * @return
       
   339 	 */
       
   340 	private ArrayList<String> checkCreatedObjects(ArrayList<String> tokenizedLine) {
       
   341 		
       
   342 		for(int i = 0 ; i < Parser.createdObjectsList.size() ; i++ ){
       
   343 			if(tokenizedLine.size()>1 && tokenizedLine.get(0).equals(Parser.createdObjectsList.get(i))){
       
   344 				if(tokenizedLine.size()>1){
       
   345 				tokenizedLine.clear();
       
   346 				break;
       
   347 				}	
       
   348 			}
       
   349 		}
       
   350 		return tokenizedLine;
       
   351 	}
       
   352 
       
   353 	/**
       
   354 	 * replace defined statments with their value.
       
   355 	 * 
       
   356 	 * @param tokenizedLine
       
   357 	 * @param parser 
       
   358 	 * @return tokenizedLine
       
   359 	 */
       
   360 	private ArrayList<String> resolveDefine(ArrayList<String> tokenizedLine) {
       
   361 		if (createdObjectsList.size()>0 && tokenizedLine != null){
       
   362 		for (int i = 0; i < tokenizedLine.size(); i++) {
       
   363 			for (int j = 0; j < createdObjectsList.size(); j++) {
       
   364 				
       
   365 			
       
   366 			if(tokenizedLine.get(i).equals(createdObjectsList.get(j)[0])){
       
   367 				tokenizedLine.remove(i);
       
   368 				tokenizedLine.add(i, createdObjectsList.get(j)[1]);
       
   369 				
       
   370 				
       
   371 				
       
   372 			}
       
   373 			}
       
   374 			
       
   375 		}
       
   376 		}
       
   377 		
       
   378 		return tokenizedLine;
       
   379 	}
       
   380 
       
   381 	/**
       
   382 	 * Add statment from define section to createdObjectsList, 
       
   383 	 * list is used to replace defined words with correct aliases
       
   384 	 * 
       
   385 	 * @param tokenizedLine
       
   386 	 */
       
   387 	private void makeDefineObjects(ArrayList<String> tokenizedLine) {
       
   388 		
       
   389 		defineAlias = tokenizedLine.get(0);
       
   390 		defineValue = tokenizedLine.get(1);
       
   391 		String[] st = new String[2];
       
   392 		st[0]=defineAlias;
       
   393 		st[1]=defineValue;
       
   394 		createdObjectsList.add(st);
       
   395 		Parser.createdMacrosList.add(defineAlias);
       
   396 		
       
   397 	}
       
   398 
       
   399 	/**
       
   400 	 * Check if first token form tokenizedLine is a valid command and invokes
       
   401 	 * methods checking parameters
       
   402 	 * 
       
   403 	 * @param commands -
       
   404 	 *            list of commands
       
   405 	 * @param tokenizedLine -
       
   406 	 *            line form editor input
       
   407 	 * @param parser -
       
   408 	 *            parser object
       
   409 	 * @return error note or null
       
   410 	 */
       
   411 	private String checkCommand(ArrayList<String> commands,
       
   412 			ArrayList<String> tokenizedLine, Parser parser) {
       
   413 		for (int i = 0; i < commands.size(); i++) {
       
   414 
       
   415 			if (tokenizedLine.size() == 0) {
       
   416 				return null;
       
   417 			}
       
   418 			if (tokenizedLine.size() > 0
       
   419 					&& tokenizedLine.get(0).equals(commands.get(i))) {
       
   420 				tokenizedLine.remove(0);
       
   421 
       
   422 				String ret = parser.checkArguments(tokenizedLine, commands
       
   423 						.get(i));
       
   424 				if (ret != null) {
       
   425 					return ret;
       
   426 
       
   427 				} else {
       
   428 					return null;
       
   429 				}
       
   430 			}
       
   431 		}
       
   432 		return errorSyntaxError;
       
   433 	}
       
   434 
       
   435 	/**
       
   436 	 * Separate passed string in to tokens
       
   437 	 * 
       
   438 	 * @param string
       
   439 	 * @return ArrayList list of tokens
       
   440 	 */
       
   441 
       
   442 	static ArrayList<String> lineTokenize(String string) {
       
   443 
       
   444 		char[] pars = string.toCharArray();
       
   445 		ArrayList<String> ret = new ArrayList<String>();
       
   446 		String set;
       
   447 		int beginpos = 0;
       
   448 		int endpos = 1;
       
   449 		boolean qclosed;
       
   450 
       
   451 		for (int i = 0; i < pars.length; i++) {
       
   452 			
       
   453 			if (pars[i] == '"') {
       
   454 				// set flag checking if guot is closed
       
   455 				qclosed = false;
       
   456 				int a = i;
       
   457 
       
   458 				if (i > 0 && pars[i - 1] == '\\') {
       
   459 					pars[i - 1] = ' ';
       
   460 
       
   461 					// begin position = i;
       
   462 					continue;
       
   463 				}
       
   464 
       
   465 				// when char before '"' is different than space.
       
   466 				if (i > 0 && !Character.isWhitespace(pars[i - 1])
       
   467 						&& (pars[i - 1] != '=')) {
       
   468 					set = new String(pars, beginpos, endpos - beginpos);
       
   469 					ret.add(set);
       
   470 
       
   471 				}
       
   472 				beginpos = i; //+ 1;
       
   473 
       
   474 				// searching for next '"' char
       
   475 				for (int j = i + 1; j < pars.length; j++) {
       
   476 
       
   477 					if (pars[j] == '"') {
       
   478 						qclosed = true;
       
   479 						if (j > 0 && pars[j - 1] == '\\') {
       
   480 
       
   481 							pars[j - 1] = ' ';
       
   482 							continue;
       
   483 						}
       
   484 						// set end position to last element
       
   485 						endpos = j+1; //j;
       
   486 
       
   487 						set = new String(pars, beginpos, endpos - beginpos);
       
   488 						ret.add(set);
       
   489 						beginpos = (j + 1);
       
   490 						i = j;
       
   491 						break;
       
   492 					}
       
   493 				}
       
   494 				if (!qclosed && pars[a] == '\"') {
       
   495 
       
   496 					set = new String(pars, a, 1);
       
   497 					beginpos = a++;
       
   498 
       
   499 					ret.add(set);
       
   500 
       
   501 				}
       
   502 			}
       
   503 			endpos = i;
       
   504 			// checking for space
       
   505 			if (Character.isWhitespace(pars[i])) {
       
   506 
       
   507 				// check if previous char is a space,
       
   508 				// if yes skip it
       
   509 				if (i > 0 && Character.isWhitespace(pars[i - 1])
       
   510 						&& i < pars.length - 1) {
       
   511 					beginpos++;
       
   512 
       
   513 				}
       
   514 				// create new token from begin position to current position
       
   515 				if (i > 0 && !Character.isWhitespace(pars[i - 1])
       
   516 						&& (pars[i - 1] != '"')) {
       
   517 					set = new String(pars, beginpos, endpos - beginpos);
       
   518 					// begin position is a next char after current position
       
   519 					beginpos = (i + 1);
       
   520 
       
   521 					ret.add(set.trim());
       
   522 				}
       
   523 			}
       
   524 			// checking for '='
       
   525 			if (pars[i] == '=') {
       
   526 
       
   527 				// when char before "=" is different than space.
       
   528 				if (i > 0 && !Character.isWhitespace(pars[i - 1])
       
   529 						&& (pars[i - 1] != '"')) {
       
   530 					set = new String(pars, beginpos, endpos - beginpos);
       
   531 
       
   532 					ret.add(set);
       
   533 					// begin position is set on = char
       
   534 
       
   535 				}// when char after "=" is different than space.
       
   536 				beginpos = i;
       
   537 				if (i < pars.length - 1 && !Character.isWhitespace(pars[i + 1])) {
       
   538 					set = new String(pars, endpos, 1);
       
   539 					ret.add(set);
       
   540 					beginpos = (i + 1);
       
   541 
       
   542 				}
       
   543 			}
       
   544 
       
   545 
       
   546 		}
       
   547 		// last tag have to be tokenized sepretly becouse last har may not be
       
   548 		// space.
       
   549 		if (endpos == pars.length - 1 && pars[(pars.length - 1)] != '\"') {
       
   550 
       
   551 			set = new String(pars, beginpos, pars.length - beginpos);
       
   552 			if (set.length() != 0 && set.toCharArray()[0] != ' ') {
       
   553 				ret.add(set);
       
   554 			}
       
   555 		}
       
   556 
       
   557 		return ret;
       
   558 
       
   559 	}
       
   560 
       
   561 	/**
       
   562 	 * Makes IEditorInput display the found errors
       
   563 	 * 
       
   564 	 * @param input
       
   565 	 * 			IEditorInput object that IMarker (error markers) 
       
   566 	 * 			of found errors will be added to
       
   567 	 */
       
   568 	private void addErrorMarkers(IEditorInput input) {
       
   569 		try {
       
   570 			
       
   571 			clearProblemMarkers();
       
   572 			if (resource == null) {
       
   573 				resource = (IResource) input.getAdapter(IResource.class);
       
   574 				if (resource == null) {
       
   575 					resource = ResourcesPlugin.getWorkspace().getRoot();
       
   576 				}
       
   577 			}
       
   578 			resource.deleteMarkers(null, true, 0);
       
   579 
       
   580 			for (int i = 0; i < problemsList.size(); i++) {
       
   581 				IMarker marker = resource.createMarker(IMarker.PROBLEM);
       
   582 				marker.setAttribute(IMarker.LINE_NUMBER,
       
   583 						problemsList.get(i).lineNumber + 1);
       
   584 				marker.setAttribute(IMarker.MESSAGE,
       
   585 						problemsList.get(i).description);
       
   586 
       
   587 				if (problemsList.get(i).type == ParseProblem.ProblemType.ERROR) {
       
   588 					marker
       
   589 							.setAttribute(IMarker.PRIORITY,
       
   590 									IMarker.PRIORITY_HIGH);
       
   591 					marker.setAttribute(IMarker.SEVERITY,
       
   592 							IMarker.SEVERITY_ERROR);
       
   593 				} else if (problemsList.get(i).type == ParseProblem.ProblemType.WARNING) {
       
   594 					marker
       
   595 							.setAttribute(IMarker.PRIORITY,
       
   596 									IMarker.PRIORITY_HIGH);
       
   597 					marker.setAttribute(IMarker.SEVERITY,
       
   598 							IMarker.SEVERITY_WARNING);
       
   599 				}
       
   600 				markersList.add(marker);
       
   601 			}
       
   602 		} catch (CoreException ex) {
       
   603 
       
   604 		}
       
   605 	}
       
   606 
       
   607 	public static ScripterSection getCurrentScripterSection(String document,
       
   608 			int offset) {
       
   609 		boolean currentSectionFound = false;
       
   610 		currentSearchOffset = 0;
       
   611 		ScripterSection currentSection = ScripterSection.NoSection;
       
   612 		ScripterSection previousSection = ScripterSection.NoSection;
       
   613 
       
   614 		while (!currentSectionFound) {
       
   615 			currentSection = findNextScripterSection(document);
       
   616 			if (currentSearchOffset > offset || currentSection == null)
       
   617 				currentSectionFound = true;
       
   618 			else {
       
   619 				previousSection = currentSection;
       
   620 			}
       
   621 		}
       
   622 		return previousSection;
       
   623 	}
       
   624 	
       
   625 	/**
       
   626 	 * This method is used by testcombiner content assistant to provide
       
   627 	 * info about keywords valid in current context
       
   628 	 * 
       
   629 	 * @param document
       
   630 	 * 			Script content
       
   631 	 * @param offset
       
   632 	 * 			Current offset of cursor in file
       
   633 	 * @return
       
   634 	 * 			Object describing if cursor is currently in a section ([Define], [Test], etc.)
       
   635 	 */
       
   636 	
       
   637 //	public static CombinerSection getCurrentCombinerSection(String document,
       
   638 //			int offset) {
       
   639 //		boolean currentSectionFound = false;
       
   640 //		currentSearchOffset = 0;
       
   641 //		CombinerSection currentSection = CombinerSection.NoSection;
       
   642 //		CombinerSection previousSection = CombinerSection.NoSection;
       
   643 //
       
   644 //		while (!currentSectionFound) {
       
   645 //			currentSection = findNextCombinerSection(document);
       
   646 //			if (currentSearchOffset > offset || currentSection == null)
       
   647 //				currentSectionFound = true;
       
   648 //			else {
       
   649 //				previousSection = currentSection;
       
   650 //			}
       
   651 //		}
       
   652 //		return previousSection;
       
   653 //	}
       
   654 	
       
   655 	/**
       
   656 	 * Utility method used by getCurrentScripterSection method
       
   657 	 * 
       
   658 	 * @param document
       
   659 	 * 			Script content
       
   660 	 * @return
       
   661 	 * 			Object describing the section that follows current section (the next 
       
   662 	 * 			section after the one in which cursor currently remains). 
       
   663 	 */
       
   664 	private static ScripterSection findNextScripterSection(String document) {
       
   665 		int currentSearchOffsetAtStart = currentSearchOffset;
       
   666 		ScripterSection section = ScripterSection.NoSection;
       
   667 		int indexOfOpeningBracket = document.indexOf("[", currentSearchOffset);
       
   668 		int indexOfClosingBracket = -1;
       
   669 		if (indexOfOpeningBracket > -1) {
       
   670 			indexOfClosingBracket = document
       
   671 					.indexOf("]", indexOfOpeningBracket);
       
   672 			if (indexOfClosingBracket > -1) {
       
   673 				String sectionWord = document.substring(
       
   674 						indexOfOpeningBracket + 1, indexOfClosingBracket);
       
   675 				if (sectionWord.equals("Test")) {
       
   676 					section = ScripterSection.TestSection;
       
   677 				} else if (sectionWord.equals("Define")) {
       
   678 					section = ScripterSection.DefineSection;
       
   679 				} else if (sectionWord.equals("New_Include_Module")) {
       
   680 					section = ScripterSection.NewIncludeModuleSection;
       
   681 				} else if (sectionWord.equals("StifSettings")) {
       
   682 					section = ScripterSection.StifSettingsSection;
       
   683 				} else if (sectionWord.equals("Data")) {
       
   684 					section = ScripterSection.DataSection;
       
   685 				}  
       
   686 				currentSearchOffset = indexOfClosingBracket + 1;
       
   687 			}
       
   688 		}
       
   689 		if (currentSearchOffset != currentSearchOffsetAtStart)
       
   690 			return section;
       
   691 		else
       
   692 			return null;
       
   693 	}
       
   694 
       
   695 	
       
   696 	/**
       
   697 	 * Utility method used by getCurrentCombinerSection method
       
   698 	 * 
       
   699 	 * @param document
       
   700 	 * 			Script content
       
   701 	 * @return
       
   702 	 * 			Object describing the section that follows current section (the next 
       
   703 	 * 			section after the one in which cursor currently remains). 
       
   704 	 */
       
   705 //	private static CombinerSection findNextCombinerSection(String document) {
       
   706 //		int currentSearchOffsetAtStart = currentSearchOffset;
       
   707 //		CombinerSection section = CombinerSection.NoSection;
       
   708 //		int indexOfOpeningBracket = document.indexOf("[", currentSearchOffset);
       
   709 //		int indexOfClosingBracket = -1;
       
   710 //		if (indexOfOpeningBracket > -1) {
       
   711 //			indexOfClosingBracket = document
       
   712 //					.indexOf("]", indexOfOpeningBracket);
       
   713 //			if (indexOfClosingBracket > -1) {
       
   714 //				String sectionWord = document.substring(
       
   715 //						indexOfOpeningBracket + 1, indexOfClosingBracket);
       
   716 //				if (sectionWord.equals("Test")) {
       
   717 //					section = CombinerSection.TestSection;
       
   718 //				} else if (sectionWord.equals("Define")) {
       
   719 //					section = CombinerSection.DefineSection;
       
   720 //				} else if (sectionWord.equals("New_Include_Module")) {
       
   721 //					section = CombinerSection.NewIncludeModuleSection;
       
   722 //				}
       
   723 //				currentSearchOffset = indexOfClosingBracket + 1;
       
   724 //			}
       
   725 //		}
       
   726 //		if (currentSearchOffset != currentSearchOffsetAtStart)
       
   727 //			return section;
       
   728 //		else
       
   729 //			return null;
       
   730 //	}
       
   731 	
       
   732 	/**
       
   733 	 * Enum That describes section of testcombiner script  
       
   734 	 */
       
   735 	public enum ScripterSection {
       
   736 		NoSection, TestSection, DefineSection, NewIncludeModuleSection, StifSettingsSection, DataSection
       
   737 	}
       
   738 
       
   739 	/**
       
   740 	 * Helper to check script and locate errors
       
   741 	 */
       
   742 	private int findSectionTagIndex(String[] tags, String tag) {
       
   743 		int index = 0;
       
   744 		while (index < tags.length && !tags[index].equals(tag))++index;
       
   745 		return index;
       
   746 	}
       
   747 	
       
   748 	private class SectionContext{
       
   749 		public SectionContext(int index, int lineNo, boolean testSection) {
       
   750 			sectionIndex = index;
       
   751 			lineNumber = lineNo;
       
   752 			isTestSection = testSection;
       
   753 		}
       
   754 		public void incTitleAtLine() {
       
   755 			if (isTestSection) {
       
   756 				++titleAtLine;
       
   757 			}
       
   758 		}
       
   759 		public void setTitleAtLine(int lineNo) {
       
   760 			if (isTestSection) {
       
   761 				titleAtLine = lineNo;
       
   762 				titleExpected = true;
       
   763 			}
       
   764 		}
       
   765 		
       
   766 		public int getTitleAtLine() {
       
   767 			return titleAtLine;
       
   768 		}
       
   769 		
       
   770 		public void setTitleExpected(boolean title) {
       
   771 			if (isTestSection) {
       
   772 				titleExpected = title;
       
   773 			}
       
   774 		}
       
   775 		
       
   776 		public boolean isTitleExpected() {
       
   777 			return titleExpected;
       
   778 		}
       
   779 		public int sectionIndex;
       
   780 		public int lineNumber;
       
   781 		public boolean isTestSection;
       
   782 		
       
   783 		// Members for [Test] section only.
       
   784 		private int titleAtLine;
       
   785 		private boolean titleExpected;
       
   786 	}
       
   787 	
       
   788 	private class SectionContextStack{
       
   789 		public SectionContextStack() {
       
   790 			contextStack = new Stack<SectionContext>();
       
   791 		}
       
   792 		
       
   793 		public void addContext(SectionContext context) {
       
   794 			contextStack.push(context);
       
   795 		}
       
   796 		
       
   797 		public boolean removeContext(int sectionIndex) {
       
   798 			if (!contextStack.empty() && contextStack.lastElement().sectionIndex == --sectionIndex) {
       
   799 				contextStack.pop();
       
   800 				return true;
       
   801 			}
       
   802 			return false;
       
   803 		}
       
   804 		
       
   805 		public boolean isCurrentSection(int i) {
       
   806 			return !contextStack.empty() && contextStack.lastElement().sectionIndex == i;
       
   807 		}
       
   808 		
       
   809 		public SectionContext[] toArray(SectionContext[] arr) {
       
   810 			return contextStack.toArray(arr);
       
   811 		}
       
   812 		
       
   813 		public SectionContext lastSectionContext() {
       
   814 			if (!contextStack.empty()) {
       
   815 				return contextStack.lastElement();
       
   816 			}
       
   817 			else {
       
   818 				return null;
       
   819 			}
       
   820 		}
       
   821 		
       
   822 		public int size() {
       
   823 			return contextStack.size();
       
   824 		}
       
   825 		
       
   826 		private Stack<SectionContext> contextStack;
       
   827 	}
       
   828 
       
   829 //	public enum CombinerSection {
       
   830 //		NoSection, TestSection, DefineSection, NewIncludeModuleSection,
       
   831 //	}
       
   832 
       
   833 
       
   834 	private List<IMarker> markersList;
       
   835 
       
   836 	private List<ParseProblem> problemsList;
       
   837 
       
   838 	private int lineNumber = -1;
       
   839 
       
   840 	ArrayList<String> objectNames = null;
       
   841 
       
   842 	ArrayList<String> definedNames = null;
       
   843 
       
   844 	ArrayList<String> testIds = null;
       
   845 
       
   846 	private static int currentSearchOffset = 0;
       
   847 
       
   848 	private String errorTitleMustBeTheFirstWord = "test case content must start with the \"title\" keyword and title following";
       
   849 
       
   850 	private String errorSyntaxError = "syntax error";
       
   851 
       
   852 	private String errorEmbeddedSlashStar = "Embedded \"/*\" not allowed";
       
   853 	
       
   854 	private String errorTailStarSlash = "Tail \"*/\"";
       
   855 	
       
   856 	private String errorMissingStarSlash = "Missing \"*/\"";
       
   857 	
       
   858 	private String errorMissingTag = "Missing tag: \"";
       
   859 	
       
   860 	private String errorNonExistingTag = "Non existing tag: \"";
       
   861 	
       
   862 	private String errorSubTagMissingTitle = "Sub Tag missing ttitle: \"";
       
   863 	
       
   864 	private String errorUnexpectedTitle = "Unexpected \"title\" keyword";
       
   865 	
       
   866 	private String errorFreeText = "Free text not allowed";
       
   867 	
       
   868 	private String errorEmbeddedSection = "Embedded section not allowed";
       
   869 	
       
   870 	private String errorSlashStarMustBeFirstWord = "/* must be at the begin of the line";
       
   871 	
       
   872 	private String errorStarSlashMustBeLastWord = "*/ must be at the end of the line";
       
   873 	
       
   874 	private String errorNonSectionCmd = "Non-section command: \"";
       
   875 	
       
   876 	private String doubleQuotation = "\"";
       
   877 
       
   878 	private IResource resource;	
       
   879 	
       
   880 	private String defineAlias;
       
   881 	
       
   882 	private String defineValue;	
       
   883 	
       
   884 	private ArrayList<String[]> createdObjectsList;
       
   885 	
       
   886 	public ArrayList<String> subSectionContent;
       
   887 }