| /* |
| * 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.modules.languages.ini.lexer; |
| |
| import org.netbeans.spi.lexer.LexerInput; |
| import org.netbeans.spi.lexer.LexerRestartInfo; |
| import org.netbeans.modules.web.common.api.ByteStack; |
| |
| @org.netbeans.api.annotations.common.SuppressWarnings({"SF_SWITCH_FALLTHROUGH", "URF_UNREAD_FIELD", "DLS_DEAD_LOCAL_STORE", "DM_DEFAULT_ENCODING"}) |
| %% |
| |
| %public |
| %class IniColoringLexer |
| %type IniTokenId |
| %function nextToken |
| %unicode |
| %caseless |
| %char |
| |
| %eofval{ |
| if(input.readLength() > 0) { |
| // backup eof |
| input.backup(1); |
| //and return the text as error token |
| return IniTokenId.INI_ERROR; |
| } else { |
| return null; |
| } |
| %eofval} |
| |
| %{ |
| |
| private ByteStack stack = new ByteStack(); |
| |
| private LexerInput input; |
| |
| public IniColoringLexer(LexerRestartInfo info) { |
| this.input = info.input(); |
| if(info.state() != null) { |
| //reset state |
| setState((LexerState) info.state()); |
| } else { |
| zzState = zzLexicalState = YYINITIAL; |
| stack.clear(); |
| } |
| |
| } |
| |
| public static final class LexerState { |
| final ByteStack stack; |
| /** the current state of the DFA */ |
| final int zzState; |
| /** the current lexical state */ |
| final int zzLexicalState; |
| |
| LexerState(ByteStack stack, int zzState, int zzLexicalState) { |
| this.stack = stack; |
| this.zzState = zzState; |
| this.zzLexicalState = zzLexicalState; |
| } |
| |
| @Override |
| public boolean equals(Object obj) { |
| if (this == obj) { |
| return true; |
| } |
| if (obj == null || obj.getClass() != this.getClass()) { |
| return false; |
| } |
| LexerState state = (LexerState) obj; |
| return (this.stack.equals(state.stack) |
| && (this.zzState == state.zzState) |
| && (this.zzLexicalState == state.zzLexicalState)); |
| } |
| |
| @Override |
| public int hashCode() { |
| int hash = 11; |
| hash = 31 * hash + this.zzState; |
| hash = 31 * hash + this.zzLexicalState; |
| if (stack != null) { |
| hash = 31 * hash + this.stack.hashCode(); |
| } |
| return hash; |
| } |
| } |
| |
| public LexerState getState() { |
| return new LexerState(stack.copyOf(), zzState, zzLexicalState); |
| } |
| |
| public void setState(LexerState state) { |
| this.stack.copyFrom(state.stack); |
| this.zzState = state.zzState; |
| this.zzLexicalState = state.zzLexicalState; |
| } |
| |
| protected int getZZLexicalState() { |
| return zzLexicalState; |
| } |
| |
| protected void popState() { |
| yybegin(stack.pop()); |
| } |
| |
| protected void pushState(final int state) { |
| stack.push(getZZLexicalState()); |
| yybegin(state); |
| } |
| |
| |
| // End user code |
| |
| %} |
| |
| WHITESPACE=[ \t]+ |
| NEWLINE=("\r"|"\n"|"\r\n") |
| D_STRING="\""([^"\""]|"\\\"")*"\"" |
| S_STRING="'"([^"'"]|"\\'")*"'" |
| EQUALS="=" |
| COMMENT=";"[^"\r""\n""\r\n"]* |
| SECTION="["[^"]""\r""\n""\r\n"]*"]" |
| KEY=[^"=""\r""\n""\r\n"";"]+ |
| QUOTED_VALUE={D_STRING} | {S_STRING} |
| UNQUOTED_VALUE=[^"\r""\n""\r\n"";"]+ |
| VALUE={WHITESPACE}*{QUOTED_VALUE}{UNQUOTED_VALUE}? | {UNQUOTED_VALUE} |
| ERROR=[^"\r""\n""\r\n"";"]+ |
| |
| %state ST_IN_BLOCK |
| %state ST_IN_SECTION |
| %state ST_AFTER_SECTION |
| %state ST_IN_KEY |
| %state ST_IN_VALUE |
| %state ST_HIGHLIGHTING_ERROR |
| |
| |
| %% |
| <YYINITIAL>.|{NEWLINE} { |
| yypushback(yylength()); |
| pushState(ST_IN_BLOCK); |
| } |
| |
| <ST_IN_BLOCK, ST_AFTER_SECTION, ST_IN_KEY, ST_IN_VALUE>{WHITESPACE} { |
| return IniTokenId.INI_WHITESPACE; |
| } |
| |
| <ST_IN_BLOCK, ST_AFTER_SECTION, ST_IN_KEY>{COMMENT} { |
| return IniTokenId.INI_COMMENT; |
| } |
| |
| <ST_IN_BLOCK> { |
| {SECTION} { |
| yypushback(yylength()); |
| pushState(ST_IN_SECTION); |
| } |
| {NEWLINE} { |
| return IniTokenId.INI_WHITESPACE; |
| } |
| . { |
| pushState(ST_IN_KEY); |
| yypushback(yylength()); |
| } |
| } |
| |
| <ST_IN_SECTION> { |
| "[" { |
| return IniTokenId.INI_SECTION_DELIM; |
| } |
| "]" { |
| popState(); |
| pushState(ST_AFTER_SECTION); |
| return IniTokenId.INI_SECTION_DELIM; |
| } |
| [^\[\]]+ { |
| return IniTokenId.INI_SECTION; |
| } |
| } |
| |
| <ST_AFTER_SECTION> { |
| {WHITESPACE} { |
| return IniTokenId.INI_WHITESPACE; |
| } |
| {COMMENT} { |
| return IniTokenId.INI_COMMENT; |
| } |
| {ERROR} { |
| return IniTokenId.INI_ERROR; |
| } |
| {NEWLINE} { |
| popState(); |
| return IniTokenId.INI_WHITESPACE; |
| } |
| } |
| |
| <ST_IN_KEY> { |
| {EQUALS} { |
| popState(); |
| pushState(ST_IN_VALUE); |
| return IniTokenId.INI_EQUALS; |
| } |
| {KEY} { |
| return IniTokenId.INI_KEY; |
| } |
| {NEWLINE} { |
| popState(); |
| return IniTokenId.INI_WHITESPACE; |
| } |
| } |
| |
| <ST_IN_VALUE> { |
| {VALUE} { |
| return IniTokenId.INI_VALUE; |
| } |
| {COMMENT} { |
| popState(); |
| return IniTokenId.INI_COMMENT; |
| } |
| {NEWLINE} { |
| popState(); |
| return IniTokenId.INI_WHITESPACE; |
| } |
| } |
| |
| /* ============================================ |
| Stay in this state until we find a whitespace. |
| After we find a whitespace we go the the prev state and try again from the next token. |
| ============================================ */ |
| <ST_HIGHLIGHTING_ERROR> { |
| {WHITESPACE} { |
| popState(); |
| return IniTokenId.INI_WHITESPACE; |
| } |
| . | {NEWLINE} { |
| return IniTokenId.INI_ERROR; |
| } |
| } |
| |
| // not needed for ini files... |
| /* ============================================ |
| This rule must be the last in the section!! |
| it should contain all the states. |
| ============================================ */ |
| /*<YYINITIAL, ST_IN_BLOCK, ST_IN_SECTION, ST_AFTER_SECTION, ST_IN_KEY, ST_IN_VALUE> { |
| . { |
| yypushback(yylength()); |
| pushState(ST_HIGHLIGHTING_ERROR); |
| } |
| {NEWLINE} { |
| yypushback(yylength()); |
| pushState(ST_HIGHLIGHTING_ERROR); |
| } |
| }*/ |