/*
* Copyright (c) 2012 Sam Harwell, Tunnel Vision Laboratories LLC
* All rights reserved.
*
* The source code of this document is proprietary work, and is not licensed for
* distribution. For information about licensing, contact Sam Harwell at:
* sam@tunnelvisionlabs.com
*/
package org.antlr.works.editor.grammar.highlighter;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.atn.ATN;
import org.antlr.v4.runtime.atn.LexerATNSimulator;
import org.antlr.v4.runtime.misc.Interval;
import org.antlr.v4.tool.Grammar;
import org.antlr.works.editor.grammar.experimental.GrammarLexer;
import org.antlr.works.editor.grammar.highlighter.generated.AbstractGrammarHighlighterLexer;
/**
*
* @author Sam Harwell
*/
public class GrammarHighlighterLexer extends AbstractGrammarHighlighterLexer {
private boolean inOptions;
private boolean inTokens;
private int _ruleType;
public GrammarHighlighterLexer(CharStream input) {
super(input);
_interp = new GrammarHighlighterATNSimulator(this, _ATN);
}
public boolean isInOptions() {
return inOptions;
}
public void setInOptions(boolean inOptions) {
this.inOptions = inOptions;
}
public boolean isInTokens() {
return inTokens;
}
public void setInTokens(boolean inTokens) {
this.inTokens = inTokens;
}
public int getRuleType() {
return _ruleType;
}
public void setRuleType(int ruleType) {
assert ruleType == GrammarLexer.TOKEN_REF || ruleType == GrammarLexer.RULE_REF || ruleType == Token.INVALID_TYPE;
this._ruleType = ruleType;
}
public boolean isInLexerRule() {
return _ruleType == GrammarLexer.TOKEN_REF;
}
@Override
protected void handleBeginArgAction() {
if (isInLexerRule()) {
pushMode(LexerCharSet);
} else {
pushMode(ArgAction);
}
}
@Override
public Token emit() {
switch (_type) {
case TOKENS:
handleAcceptPositionForKeyword("tokens");
setInTokens(true);
break;
case OPTIONS:
handleAcceptPositionForKeyword("options");
setInOptions(true);
break;
case CHANNELS:
handleAcceptPositionForKeyword("channels");
break;
case LABEL:
handleAcceptPositionForIdentifier();
if (isInOptions()) {
_type = ValidGrammarOption;
} else if (isInTokens()) {
_type = IDENTIFIER;
}
break;
case RCURLY:
setInTokens(false);
setInOptions(false);
break;
case SEMI:
setRuleType(Token.INVALID_TYPE);
break;
case IDENTIFIER:
if (_ruleType == Token.INVALID_TYPE) {
String firstChar = _input.getText(Interval.of(_tokenStartCharIndex, _tokenStartCharIndex));
if (Grammar.isTokenName(firstChar)) {
_ruleType = GrammarLexer.TOKEN_REF;
} else {
_ruleType = GrammarLexer.RULE_REF;
}
}
break;
default:
break;
}
return super.emit();
}
private boolean handleAcceptPositionForIdentifier() {
String tokenText = getText();
int identifierLength = 0;
while (identifierLength < tokenText.length() && isIdentifierChar(tokenText.charAt(identifierLength))) {
identifierLength++;
}
if (getInputStream().index() > _tokenStartCharIndex + identifierLength) {
int offset = identifierLength - 1;
getInterpreter().resetAcceptPosition(getInputStream(), _tokenStartCharIndex + offset, _tokenStartLine, _tokenStartCharPositionInLine + offset);
return true;
}
return false;
}
private boolean handleAcceptPositionForKeyword(String keyword) {
if (getInputStream().index() > _tokenStartCharIndex + keyword.length()) {
int offset = keyword.length() - 1;
getInterpreter().resetAcceptPosition(getInputStream(), _tokenStartCharIndex + offset, _tokenStartLine, _tokenStartCharPositionInLine + offset);
return true;
}
return false;
}
@Override
public GrammarHighlighterATNSimulator getInterpreter() {
return (GrammarHighlighterATNSimulator)super.getInterpreter();
}
private static boolean isIdentifierChar(char c) {
return Character.isLetterOrDigit(c) || c == '_';
}
protected static class GrammarHighlighterATNSimulator extends LexerATNSimulator {
public GrammarHighlighterATNSimulator(Lexer recog, ATN atn) {
super(recog, atn);
}
protected void resetAcceptPosition(CharStream input, int index, int line, int charPositionInLine) {
input.seek(index);
this.line = line;
this.charPositionInLine = charPositionInLine;
consume(input);
}
}
}