package org.nodeclipse.enide.editors.gradle.editors;
import java.util.LinkedList;
import java.util.List;
/**
* Gradle file structure
*
* parsing only first level {} block, i.e. it is made not to be perfect, but minimal enough to give Outline
*
* Does not depend on Groovy, Greclipse or Gradle Tooling API
* */
//specially made package private
class GradlePage {
static class Element{
public static final Element EMPTY = new Element("");
String name;
int line;
int position;
Element() {
}
Element(String string) {
name = string;
}
}
static class Node extends Element{
//the same as Element plus:
List<Node> children = new LinkedList<Node>();
Node(String string) {
super(string);
}
Node(Element el) {
name = el.name;
line = el.line;
position = el.position;
}
@Override
public String toString() {
return name+" (L"+line+','+position+")";
}
}
String text = "";
int curLine = 1;
int curPosition = 1;
int curIndex = 0;
List<Element> elements = new LinkedList<Element>();
List<Node> nodes = new LinkedList<Node>();
GradlePage(String text) {
this.text=text;
parse();
}
void parse() {
Element lexem = nextLexem();
while ( lexem != Element.EMPTY ){
if (lexem.name.equals("{")){
createNode(lexem);
parseBlock();
}
lexem = nextLexem();
}
}//parse
private void createNode(Element el) {
// get previous
int index = elements.indexOf(el);
if (index>0){ //get previous
index--;
el = elements.get(index);
}
nodes.add(new Node(el));
}//createNode
private void parseBlock() {
Element prev, lexem;
lexem = nextLexem();
while ( !lexem.name.equals("}") && lexem != Element.EMPTY ){
if (lexem.name.equals("{")) {
createNode(lexem);
parseBlock();
}
prev = lexem;
lexem = nextLexem();
}
}
private Element nextLexem() {
Element el = nextLexemWithoutLog();
elements.add(el);
log(el.name);
//log(el.toString());
return el;
}
public static final String LETTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static final String LETTERS_ALL_CASES = LETTERS + LETTERS.toLowerCase();
public static final String LETTERS_ALL_CASES_AND_UNDERLINE = LETTERS_ALL_CASES + '_';
public static final String DIGITS = "0123456789";
public static final String NUMBER_PARTS = DIGITS + ".eE";
/** get lexical element literal, number or other like (){}/*-+
*/
//TODO comments and strings
private Element nextLexemWithoutLog() {
if (curIndex >= text.length()) {
return Element.EMPTY;
}
char c;
// skip white spaces
loop1: while (curIndex < text.length()) {
c = text.charAt(curIndex);
switch (c) {
case '\n': {
curLine++;
curPosition = 1;
break;
}
//TODO look at Character.isWhitespace(c)
case '\r':
case '\t':
case ' ':
break;
default:
break loop1;
}
curIndex++;
}
if (curIndex >= text.length()) {// when file ends with spaces or new line
return Element.EMPTY;
}
c = text.charAt(curIndex);
if (LETTERS_ALL_CASES.indexOf(c, 0) >= 0){
// Element el = new Element();
// el.line = curLine;
// el.position = curPosition;
// el.name = ""+c;
//
// curIndex++;
// while (curIndex < text.length()) {
// c = text.charAt(curIndex);
// if (LETTERS_ALL_CASES_AND_UNDERLINE.indexOf(c, 0) < 0){
// return el;
// }
// el.name += c;
// curIndex++;
// }
// return el; //when file ends with literal
return readElementTail(c, LETTERS_ALL_CASES_AND_UNDERLINE);
}
//
else if (DIGITS.indexOf(c, 0) >= 0){
return readElementTail(c, NUMBER_PARTS);
}
// Element el = new Element();
// el.line = curLine;
// el.position = curPosition;
// el.name = ""+c;
// curIndex++;
//
// return el;
return readElementTail(c, "");
}//nextLexem
private Element readElementTail(char c, final String CSET) {
Element el = new Element();
el.line = curLine;
el.position = curPosition;
el.name = ""+c;
curIndex++;
while (curIndex < text.length()) {
c = text.charAt(curIndex);
if (CSET.indexOf(c, 0) < 0){
return el;
}
el.name += c;
curIndex++;
}
return el; //when file ends with literal
}
static void log(String s){
System.out.println(s);
}
}