package org.cassandraunit.dataset.cql; import java.util.ArrayList; import java.util.List; /** * @author Steve Nicolai */ /* see the full CQL grammar at: * https://github.com/apache/cassandra/blob/trunk/src/java/org/apache/cassandra/cql3/Cql.g * * This parser a series of lines, removes comments and breaks the lines into statements * at semicolon boundaries. */ public class SimpleCQLLexer { String text; enum LexState { DEFAULT, INSINGLELINECOMMENT, INMULTILINECOMMENT, INQUOTESTRING, INSQUOTESTRING, } LexState state; int pos; public SimpleCQLLexer(List<String> lines) { StringBuffer t = new StringBuffer(); for (String l : lines) { t.append(l.trim()); t.append('\n'); } text = t.toString(); pos = 0; state = LexState.DEFAULT; } char getChar() { if (pos < text.length()) return text.charAt(pos++); else return 0; } char peekAhead() { if (pos < text.length()) return text.charAt(pos); // don't advance else return 0; } /* Skip the peekAhead character and not copy it to the output. */ void advance() { pos++; } List<String> getStatements() { List<String> statements = new ArrayList<String>(); StringBuffer statementUnderConstruction = new StringBuffer(); char c; while ((c = getChar()) != 0) { switch (state) { case DEFAULT: if (c == '/' && peekAhead() == '/') { state = LexState.INSINGLELINECOMMENT; advance(); } else if (c == '-' && peekAhead() == '-') { state = LexState.INSINGLELINECOMMENT; advance(); } else if (c == '/' && peekAhead() == '*') { state = LexState.INMULTILINECOMMENT; advance(); } else if (c == '\n') { statementUnderConstruction.append(' '); } else { statementUnderConstruction.append(c); if (c == '\"') { state = LexState.INQUOTESTRING; } else if (c == '\'') { state = LexState.INSQUOTESTRING; } else if (c == ';') { statements.add(statementUnderConstruction.toString().trim()); statementUnderConstruction.setLength(0); } } break; case INSINGLELINECOMMENT: if (c == '\n') { state = LexState.DEFAULT; } break; case INMULTILINECOMMENT: if (c == '*' && peekAhead() == '/') { state = LexState.DEFAULT; advance(); } break; case INQUOTESTRING: statementUnderConstruction.append(c); if (c == '"') { if (peekAhead() == '"') { statementUnderConstruction.append(getChar()); } else { state = LexState.DEFAULT; } } break; case INSQUOTESTRING: statementUnderConstruction.append(c); if (c == '\'') { if (peekAhead() == '\'') { statementUnderConstruction.append(getChar()); } else { state = LexState.DEFAULT; } } break; } } String tmp = statementUnderConstruction.toString().trim(); if (tmp.length() > 0) { statements.add(tmp); } return statements; } }