/** * <copyright> * * Copyright (c) 2002-2006 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM - Initial API and implementation * * </copyright> * * $Id: RoseLexer.java,v 1.3 2006/12/28 06:56:06 marcelop Exp $ */ package com.sap.emf.importer.moin.rose.parser; import java.util.ArrayList; import java.util.List; import java.util.StringTokenizer; /** * A lexical analyzer that creates vector of tokens out of Rose file. */ public class RoseLexer { protected RoseLoader roseLoader; protected List<RoseToken> tokens = new ArrayList<RoseToken>(); protected int currentElement = 0; protected boolean isList = false; protected int lineCounter = 0; public RoseLexer(RoseLoader roseLoader) { this.roseLoader = roseLoader; } protected void getNextBlock() { RoseToken roseToken = null; if (tokens.size() > currentElement) { roseToken = tokens.get(currentElement); } tokens.clear(); if (roseToken != null) { tokens.add(roseToken); } currentElement = 0; System.gc(); readLines(); } public RoseToken getNext() { if (currentElement >= tokens.size()) { getNextBlock(); } if (currentElement < tokens.size()) { RoseToken roseToken = tokens.get(currentElement); currentElement++; return roseToken; } else { return null; } } public RoseToken peekNext() { if (currentElement >= tokens.size()) { getNextBlock(); } if (currentElement < tokens.size()) { return tokens.get(currentElement); } else { return null; } } public void printNeighbors() { int count = 100; if (currentElement < 100) { count = currentElement; } for (int i = currentElement - count; i <= currentElement; i++) { RoseToken tok = tokens.get(i); System.out.println(tok.getToken()); } } public void readLines() { for (int k = 0; k < 1000; k++) { String currentLine = roseLoader.readLine(); if (currentLine == null) { return; } lineCounter++; if (currentLine.length() == 0) { k--; continue; } if (currentLine.charAt(0) == '|') { RoseToken roseToken = new RoseToken(RoseToken.VERTICAL_BAR, ""); roseToken.lineNum = lineCounter; tokens.add(roseToken); currentLine = currentLine.substring(1); roseToken = new RoseToken(RoseToken.STRING, currentLine); roseToken.lineNum = lineCounter; tokens.add(roseToken); continue; } StringTokenizer stringTokenizer = new StringTokenizer(currentLine); for (int i = 0; stringTokenizer.hasMoreTokens();) { String tok = stringTokenizer.nextToken(); if (tok.equals("#")) { break; } currentLine = currentLine.substring(currentLine.indexOf(tok)); if (tok.equals("(object")) { isList = false; RoseToken roseToken = new RoseToken(RoseToken.LEFT_PAREN, ""); roseToken.lineNum = lineCounter; tokens.add(roseToken); roseToken = new RoseToken(RoseToken.OBJECT, ""); roseToken.lineNum = lineCounter; tokens.add(roseToken); currentLine = currentLine.substring(7).trim(); // 7 is the size of (object processToTheEnd(currentLine, lineCounter); break; } else if (tok.equals("(list")) { isList = true; RoseToken roseToken = new RoseToken(RoseToken.LEFT_PAREN, ""); roseToken.lineNum = lineCounter; tokens.add(roseToken); roseToken = new RoseToken(RoseToken.LIST, ""); roseToken.lineNum = lineCounter; tokens.add(roseToken); currentLine = currentLine.substring(5).trim(); // 5 is the size of (list processToTheEnd(currentLine, lineCounter); break; } else if (tok.equals("(value")) { isList = false; RoseToken roseToken = new RoseToken(RoseToken.LEFT_PAREN, ""); roseToken.lineNum = lineCounter; tokens.add(roseToken); roseToken = new RoseToken(RoseToken.VALUE, ""); roseToken.lineNum = lineCounter; tokens.add(roseToken); currentLine = currentLine.substring(6).trim(); // 6 is the size of (value processValueToTheEnd(currentLine, lineCounter); break; } else if (i == 0 && tok.charAt(0) == ')') { int rightParenNum = 0; String temp = tok; while (temp.length() > 0 && temp.charAt(temp.length() - 1) == ')') { rightParenNum++; temp = temp.substring(0, temp.length() - 1); } for (int j = 0; j < rightParenNum; j++) { isList = false; RoseToken roseToken = new RoseToken(RoseToken.RIGHT_PAREN, ""); roseToken.lineNum = lineCounter; tokens.add(roseToken); } break; } else { if (i == 0) { if (isList) { int rightParenNum = 0; String temp = currentLine.trim(); while (temp.charAt(temp.length() - 1) == ')') { rightParenNum++; temp = temp.substring(0, temp.length() - 1); } if (currentLine.charAt(0) == '(') { rightParenNum--; temp += ")"; } RoseToken roseToken = new RoseToken(RoseToken.STRING, temp); roseToken.lineNum = lineCounter; tokens.add(roseToken); for (int j = 0; j < rightParenNum; j++) { isList = false; roseToken = new RoseToken(RoseToken.RIGHT_PAREN, ""); roseToken.lineNum = lineCounter; tokens.add(roseToken); } break; } else { isList = false; RoseToken roseToken = new RoseToken(RoseToken.KEY, tok); roseToken.lineNum = lineCounter; tokens.add(roseToken); } } else { isList = false; currentLine = currentLine.trim(); processToTheEnd(currentLine, lineCounter); break; } } i++; } } } protected void processToTheEnd(String temp, int lineCounter) { if (temp.length() == 0) { RoseToken roseToken = new RoseToken(RoseToken.STRING, temp); roseToken.lineNum = lineCounter; tokens.add(roseToken); return; } int indFirst = temp.indexOf("\""); int indLast = temp.lastIndexOf("\""); if (indFirst != -1 && indFirst == indLast) { // Only one open quote. // String currentLine = roseLoader.readLine(); temp += currentLine; while (currentLine.indexOf("\"") == -1) { currentLine = roseLoader.readLine(); temp += currentLine; } } int rightParenNum = 0; while (temp.charAt(temp.length() - 1) == ')') { rightParenNum++; temp = temp.substring(0, temp.length() - 1); } if (temp.charAt(0) == '(') { rightParenNum--; temp += ")"; } RoseToken roseToken = new RoseToken(RoseToken.STRING, temp); roseToken.lineNum = lineCounter; tokens.add(roseToken); for (int i = 0; i < rightParenNum; i++) { isList = false; roseToken = new RoseToken(RoseToken.RIGHT_PAREN, ""); roseToken.lineNum = lineCounter; tokens.add(roseToken); } } protected void processValueToTheEnd(String temp, int lineCounter) { if (temp.length() == 0) { RoseToken roseToken = new RoseToken(RoseToken.STRING, temp); roseToken.lineNum = lineCounter; tokens.add(roseToken); return; } int rightParenNum = 0; while (temp.charAt(temp.length() - 1) == ')') { rightParenNum++; temp = temp.substring(0, temp.length() - 1); } if (temp.charAt(0) == '(') { rightParenNum--; temp += ")"; } String firstWord = temp; String restOfString = ""; int indexOfSpace = temp.indexOf(" "); if (indexOfSpace == -1) { indexOfSpace = temp.indexOf("\t"); } if (indexOfSpace != -1) { firstWord = temp.substring(0, indexOfSpace); restOfString = temp.substring(indexOfSpace).trim(); } RoseToken roseToken = new RoseToken(RoseToken.STRING, firstWord); roseToken.lineNum = lineCounter; tokens.add(roseToken); if (restOfString.length() > 0) { roseToken = new RoseToken(RoseToken.STRING, restOfString); roseToken.lineNum = lineCounter; tokens.add(roseToken); } for (int i = 0; i < rightParenNum; i++) { isList = false; roseToken = new RoseToken(RoseToken.RIGHT_PAREN, ""); roseToken.lineNum = lineCounter; tokens.add(roseToken); } } }