org.snapscript.parse.TokenIndexer Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of snap Show documentation
Show all versions of snap Show documentation
Dynamic scripting for the JVM
package org.snapscript.parse;
import static org.snapscript.parse.TokenType.BINARY;
import static org.snapscript.parse.TokenType.DECIMAL;
import static org.snapscript.parse.TokenType.HEXIDECIMAL;
import static org.snapscript.parse.TokenType.IDENTIFIER;
import static org.snapscript.parse.TokenType.LITERAL;
import static org.snapscript.parse.TokenType.QUALIFIER;
import static org.snapscript.parse.TokenType.SPACE;
import static org.snapscript.parse.TokenType.TEMPLATE;
import static org.snapscript.parse.TokenType.TEXT;
import static org.snapscript.parse.TokenType.TYPE;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class TokenIndexer {
private final LengthComparator comparator;
private final LineExtractor extractor;
private final GrammarIndexer indexer;
private final TextReader reader;
private final List values;
private final short[] lines;
public TokenIndexer(GrammarIndexer indexer, String resource, char[] original, char[] source, short[] lines, short[] types) {
this.extractor = new LineExtractor(resource, original);
this.reader = new TextReader(source, types);
this.comparator = new LengthComparator();
this.values = new ArrayList();
this.indexer = indexer;
this.lines = lines;
}
public short[] index(List tokens) {
if(values.isEmpty()) {
List literals = indexer.list();
for(String literal : literals) {
values.add(literal);
}
Collections.sort(values, comparator);
}
return scan(tokens);
}
private short[] scan(List tokens) {
int count = reader.count();
while (true) {
int mark = reader.mark();
if(mark >= count) {
return create(tokens);
}
int line = lines[mark];
Token token = literal(line);
if (token == null) {
token = space(line);
}
if (token == null) {
token = template(line);
}
if (token == null) {
token = text(line);
}
if(token == null) {
token = type(line);
}
if(token == null) {
token = identifier(line);
}
if(token == null) {
token = binary(line);
}
if(token == null) {
token = hexidecimal(line);
}
if(token == null) {
token = decimal(line);
}
if(token == null) {
throw new ParseException("Could not parse token at line " + lines[mark]);
}
tokens.add(token);
}
}
private short[] create(List tokens) {
int length = tokens.size();
if(length > 0) {
short[] masks = new short[length];
for(int i = 0; i < length; i++) {
Token token = tokens.get(i);
if(token != null) {
masks[i] = token.getType();
}
}
return masks;
}
return new short[]{};
}
private Token type(int number) {
Line line = extractor.extract(number);
String token = reader.type();
if (token != null) {
return new StringToken(token, line, TYPE.mask | QUALIFIER.mask | IDENTIFIER.mask);
}
return null;
}
private Token identifier(int number) {
Line line = extractor.extract(number);
String token = reader.identifier();
if (token != null) {
return new StringToken(token, line, IDENTIFIER.mask | QUALIFIER.mask);
}
return null;
}
private Token decimal(int number) {
Line line = extractor.extract(number);
Number token = reader.decimal();
if (token != null) {
return new NumberToken(token, line, DECIMAL.mask);
}
return null;
}
private Token binary(int number) {
Line line = extractor.extract(number);
Number token = reader.binary();
if (token != null) {
return new NumberToken(token, line, BINARY.mask | DECIMAL.mask);
}
return null;
}
private Token hexidecimal(int number) {
Line line = extractor.extract(number);
Number token = reader.hexidecimal();
if (token != null) {
return new NumberToken(token, line, HEXIDECIMAL.mask | DECIMAL.mask);
}
return null;
}
private Token template(int number) {
Line line = extractor.extract(number);
String token = reader.template();
if (token != null) {
return new StringToken(token, line, TEMPLATE.mask);
}
return null;
}
private Token text(int number) {
Line line = extractor.extract(number);
String token = reader.text();
if (token != null) {
return new StringToken(token, line, TEXT.mask);
}
return null;
}
private Token space(int number) {
Line line = extractor.extract(number);
Character token = reader.space();
if (token != null) {
return new CharacterToken(token, line, SPACE.mask);
}
return null;
}
private Token literal(int number) {
Line line = extractor.extract(number);
for (String literal : values) {
int mark = reader.mark();
String token = reader.literal(literal);
if (token != null) {
int length = token.length();
Character last = token.charAt(length - 1);
Character peek = reader.peek();
if (identifier(last) && identifier(peek)) {
reader.reset(mark);
} else {
if(identifier(last) && special(peek)) {
return new StringToken(token, line, LITERAL.mask | IDENTIFIER.mask | QUALIFIER.mask);
}
return new StringToken(token, line, LITERAL.mask);
}
}
}
return null;
}
private boolean identifier(Character value) {
if (value != null) {
char code = value.charValue();
if(code >= 'a' && code <='z') {
return true;
}
if(code >= 'A' && code <= 'Z') {
return true;
}
return code >= '0' && code <= '9';
}
return false;
}
private boolean special(Character value) {
if(value != null) {
char code = value.charValue();
switch(code) {
case ')': case '(':
case '.': case '?':
case ',':
return true;
}
}
return false;
}
}