All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.netbeans.lib.java.lexer.JavadocLexer Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.netbeans.lib.java.lexer;

import org.netbeans.api.java.lexer.JavadocTokenId;
import org.netbeans.api.lexer.Token;
import org.netbeans.spi.lexer.Lexer;
import org.netbeans.spi.lexer.LexerInput;
import org.netbeans.spi.lexer.LexerRestartInfo;
import org.netbeans.spi.lexer.TokenFactory;
import org.netbeans.spi.lexer.TokenPropertyProvider;

/**
 * Lexical analyzer for javadoc language.
 * @author Miloslav Metelka
 * @version 1.00
 */

public class JavadocLexer implements Lexer {

    private static final int EOF = LexerInput.EOF;

    private LexerInput input;
    
    private TokenFactory tokenFactory;
    
    private Integer state = null;
    
    public JavadocLexer(LexerRestartInfo info) {
        this.input = info.input();
        this.tokenFactory = info.tokenFactory();
        this.state = (Integer) info.state();        
    }
    
    public Object state() {
        return state;
    }
    
    public Token nextToken() {
        int ch = input.read();
        
        if (ch == EOF) {
            return null;
        }
        
        if (Character.isJavaIdentifierStart(ch)) {
            //TODO: EOF
            while (Character.isJavaIdentifierPart(input.read()))
                ;
            
            input.backup(1);
            if (state != null && state == 2) {
                state = 1;
                return token(JavadocTokenId.IDENT, "javadoc-identifier"); //NOI18N
            }
            if (state == null) {
                state = 1;
            }
            return token(JavadocTokenId.IDENT);
        }
        
        switch (ch) {
            case '@':
                if (state != null) {
                    return otherText(ch);
                }
                String tag = "";
                while (true) {
                    ch = input.read();
                    if (!Character.isLetter(ch)) {
                        state = "param".equals(tag) ? 2 : "code".equals(tag) || "literal".equals(tag) ? 3 : 1; //NOI18N
                        input.backup(1);
                        return tokenFactory.createToken(JavadocTokenId.TAG, input.readLength());
                    } else {
                        tag+=new String(Character.toChars(ch));
                    }
                }
            case '<':
                if (state != null && state == 3) {
                    return otherText(ch);
                }
                int backupCounter = 0;
                boolean newline = false;
                boolean asterisk = false;
                while (true) {
                    ch = input.read();
                    ++backupCounter;
                    if (ch == EOF) {
                        state = null;
                        return token(JavadocTokenId.HTML_TAG);
                    } else if (ch == '>') {
                        if (state != null && state == 2) {
                            state = 1;
                            return token(JavadocTokenId.IDENT, "javadoc-identifier"); //NOI18N
                        }
                        state = 1;
                        return token(JavadocTokenId.HTML_TAG);
                    } else if (ch == '<') {
                        state = 1;
                        input.backup(1);
                        return token(JavadocTokenId.HTML_TAG);
                    } else if (ch == '\n') {
                        state = null;
                        backupCounter = 1;
                        newline = true;
                        asterisk = false;
                    } else if (newline && ch == '@') {
                        input.backup(backupCounter);
                        return token(JavadocTokenId.HTML_TAG);
                    } else if (newline && !asterisk && ch == '*') {
                        asterisk = true;
                    } else if (newline && !Character.isWhitespace(ch)) {
                        newline = false;
                    }
                }
            case '.':
                if (state == null) {
                    state = 1;
                }
                return token(JavadocTokenId.DOT);
            case '#':
                if (state == null) {
                    state = 1;
                }
                return token(JavadocTokenId.HASH);
            default:
                return otherText(ch);
        } // end of switch (ch)
    }

    private Token otherText(int ch) {
        boolean newline = state == null;
        boolean leftbr = false;
        while (true) {
            if (Character.isJavaIdentifierStart(ch)) {
                if ((newline || leftbr) && state != null && state != 3) {
                    state = null;
                }
                input.backup(1);
                return token(JavadocTokenId.OTHER_TEXT);
            }
            switch (ch) {
                case '<':
                    if (state != null && state == 3) {
                        leftbr = false;
                        newline = false;
                        break;
                    }
                case '.':
                case '#':
                    input.backup(1);
                case EOF:
                    return token(JavadocTokenId.OTHER_TEXT);
                case '@':
                    if ((newline || leftbr) && (state == null || state != 3)) {
                        state = null;
                        input.backup(1);                        
                        return token(JavadocTokenId.OTHER_TEXT);
                    }
                    leftbr = false;
                    newline = false;
                    break;
                case '{':
                    leftbr = true;
                    newline = false;
                    break;
                case '\n':
                    newline = true;
                    break;
                case '}':
                    if (state != null && state == 3) {
                        state = 1;
                        if (input.readLength() > 1)
                            input.backup(1);
                        return token(JavadocTokenId.OTHER_TEXT);
                    }
                    leftbr = false;
                    newline = false;
                    break;
                case '/':
                    //TODO: check comment type?
                    if (newline) {
                        if (input.read() == '/') {
                            if (input.read() == '/') {
                                break;
                            } else {
                                input.backup(1);
                            }
                        } else {
                            input.backup(1);
                        }
                        newline = false; //for fall-through:
                    }
                case '*':
                    if (newline) {
                        break;
                    }
                default:
                    if (!Character.isWhitespace(ch)) {
                        leftbr = false;
                        newline = false;
                    }
            }
            ch = input.read();
        }
    }

    private Token token(JavadocTokenId id) {
        return tokenFactory.createToken(id);
    }

    private Token token(JavadocTokenId id, final Object property) {
        return tokenFactory.createPropertyToken(id, input.readLength(), new TokenPropertyProvider() {

        @Override
        public Object getValue(Token token, Object key) {
            if (property.equals(key)) 
                return true; 
            return null;
        }
        
    });
    }

    public void release() {
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy