/*
!=======================================================================
!
!  PROGRAM  PHASE-Viewer  (PHASE-Viewer 2014.01 ver.3.3.0)
!
!  Created on ----
!  AUTHOR(S): KOGA, Junichiro
!  File : SQLTokenMarker.java
!  
!  Contact address :  Phase System Consortium
!                     E-mail: phase_system@nims.go.jp URL https://azuma.nims.go.jp
!
!
!   Since 2002, this program set had been intensively developed as a part of the following 
!  national projects supported by the Ministry of Education, Culture, Sports, Science and
!  Technology (MEXT) of Japan; "Frontier Simulation Software for Industrial Science
!  (FSIS)" from 2002 to 2005, "Revolutionary Simulation Software (RSS21)" from 2006 to
!  2008. "Research and Development of Innovative Simulation Software (RISS)" from 2008
!  to 2013. These projects is lead by the Center for Research on Innovative Simulation 
!  Software (CISS), the Institute of Industrial Science (IIS), the University of Tokyo.
!   Since 2013, this program set has been further developed centering on PHASE System
!  Consortium. 
!   The activity of development of this program set has been supervised by Takahisa Ohno.
!
!=======================================================================
 */

package ciss.phase_viewer.pub.jeditsyntax;

import javax.swing.text.Segment;

/**
 * SQL token marker.
 * 
 * @author mike dillon
 * @version $Id: SQLTokenMarker.java,v 1.6 1999/04/19 05:38:20 sp Exp $
 */
public class SQLTokenMarker extends TokenMarker {
    private int offset, lastOffset, lastKeyword, length;

    // public members
    public SQLTokenMarker(KeywordMap k) {
        this(k, false);
    }

    public SQLTokenMarker(KeywordMap k, boolean tsql) {
        keywords = k;
        isTSQL = tsql;
    }

    public byte markTokensImpl(byte token, Segment line, int lineIndex) {
        offset = lastOffset = lastKeyword = line.offset;
        length = line.count + offset;

        loop: for (int i = offset; i < length; i++) {
            switch (line.array[i]) {
            case '*':
                if (token == Token.COMMENT1 && length - i >= 1
                        && line.array[i + 1] == '/') {
                    token = Token.NULL;
                    i++;
                    addToken((i + 1) - lastOffset, Token.COMMENT1);
                    lastOffset = i + 1;
                } else if (token == Token.NULL) {
                    searchBack(line, i);
                    addToken(1, Token.OPERATOR);
                    lastOffset = i + 1;
                }
                break;
            case '[':
                if (token == Token.NULL) {
                    searchBack(line, i);
                    token = Token.LITERAL1;
                    literalChar = '[';
                    lastOffset = i;
                }
                break;
            case ']':
                if (token == Token.LITERAL1 && literalChar == '[') {
                    token = Token.NULL;
                    literalChar = 0;
                    addToken((i + 1) - lastOffset, Token.LITERAL1);
                    lastOffset = i + 1;
                }
                break;
            case '.':
            case ',':
            case '(':
            case ')':
                if (token == Token.NULL) {
                    searchBack(line, i);
                    addToken(1, Token.NULL);
                    lastOffset = i + 1;
                }
                break;
            case '+':
            case '%':
            case '&':
            case '|':
            case '^':
            case '~':
            case '<':
            case '>':
            case '=':
                if (token == Token.NULL) {
                    searchBack(line, i);
                    addToken(1, Token.OPERATOR);
                    lastOffset = i + 1;
                }
                break;
            case ' ':
            case '\t':
                if (token == Token.NULL) {
                    searchBack(line, i, false);
                }
                break;
            case ':':
                if (token == Token.NULL) {
                    addToken((i + 1) - lastOffset, Token.LABEL);
                    lastOffset = i + 1;
                }
                break;
            case '/':
                if (token == Token.NULL) {
                    if (length - i >= 2 && line.array[i + 1] == '*') {
                        searchBack(line, i);
                        token = Token.COMMENT1;
                        lastOffset = i;
                        i++;
                    } else {
                        searchBack(line, i);
                        addToken(1, Token.OPERATOR);
                        lastOffset = i + 1;
                    }
                }
                break;
            case '-':
                if (token == Token.NULL) {
                    if (length - i >= 2 && line.array[i + 1] == '-') {
                        searchBack(line, i);
                        addToken(length - i, Token.COMMENT1);
                        lastOffset = length;
                        break loop;
                    } else {
                        searchBack(line, i);
                        addToken(1, Token.OPERATOR);
                        lastOffset = i + 1;
                    }
                }
                break;
            case '!':
                if (isTSQL
                        && token == Token.NULL
                        && length - i >= 2
                        && (line.array[i + 1] == '='
                                || line.array[i + 1] == '<' || line.array[i + 1] == '>')) {
                    searchBack(line, i);
                    addToken(1, Token.OPERATOR);
                    lastOffset = i + 1;
                }
                break;
            case '"':
            case '\'':
                if (token == Token.NULL) {
                    token = Token.LITERAL1;
                    literalChar = line.array[i];
                    addToken(i - lastOffset, Token.NULL);
                    lastOffset = i;
                } else if (token == Token.LITERAL1
                        && literalChar == line.array[i]) {
                    token = Token.NULL;
                    literalChar = 0;
                    addToken((i + 1) - lastOffset, Token.LITERAL1);
                    lastOffset = i + 1;
                }
                break;
            default:
                break;
            }
        }
        if (token == Token.NULL)
            searchBack(line, length, false);
        if (lastOffset != length)
            addToken(length - lastOffset, token);
        return token;
    }

    // protected members
    protected boolean isTSQL = false;

    // private members
    private KeywordMap keywords;
    private char literalChar = 0;

    private void searchBack(Segment line, int pos) {
        searchBack(line, pos, true);
    }

    private void searchBack(Segment line, int pos, boolean padNull) {
        int len = pos - lastKeyword;
        byte id = keywords.lookup(line, lastKeyword, len);
        if (id != Token.NULL) {
            if (lastKeyword != lastOffset)
                addToken(lastKeyword - lastOffset, Token.NULL);
            addToken(len, id);
            lastOffset = pos;
        }
        lastKeyword = pos + 1;
        if (padNull && lastOffset < pos)
            addToken(pos - lastOffset, Token.NULL);
    }
}
