001: /*
002: * VerilogMode.java
003: *
004: * Copyright (C) 2002 Peter Graves
005: * $Id: VerilogMode.java,v 1.1.1.1 2002/09/24 16:07:56 piso Exp $
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License
009: * as published by the Free Software Foundation; either version 2
010: * of the License, or (at your option) any later version.
011: *
012: * This program is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
015: * GNU General Public License for more details.
016: *
017: * You should have received a copy of the GNU General Public License
018: * along with this program; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
020: */
021:
022: package org.armedbear.j;
023:
024: import java.awt.event.KeyEvent;
025:
026: public final class VerilogMode extends AbstractMode implements
027: Constants, Mode {
028: private static final VerilogMode mode = new VerilogMode();
029:
030: private VerilogMode() {
031: super (VERILOG_MODE, VERILOG_MODE_NAME);
032: keywords = new Keywords(this );
033: }
034:
035: public static VerilogMode getMode() {
036: return mode;
037: }
038:
039: public String getCommentStart() {
040: return "// ";
041: }
042:
043: public Formatter getFormatter(Buffer buffer) {
044: return new VerilogFormatter(buffer);
045: }
046:
047: protected void setKeyMapDefaults(KeyMap km) {
048: km.mapKey(KeyEvent.VK_TAB, CTRL_MASK, "insertTab");
049: km.mapKey(KeyEvent.VK_TAB, 0, "tab");
050: km.mapKey(KeyEvent.VK_ENTER, 0, "newlineAndIndent");
051: km.mapKey(KeyEvent.VK_T, CTRL_MASK, "findTag");
052: km.mapKey(KeyEvent.VK_PERIOD, ALT_MASK, "findTagAtDot");
053: km.mapKey(KeyEvent.VK_F12, 0, "wrapComment");
054: // Duplicate mapping to support IBM 1.3 for Linux.
055: km.mapKey(0xffc9, 0, "wrapComment"); // F12
056: }
057:
058: public boolean isTaggable() {
059: return true;
060: }
061:
062: public Tagger getTagger(SystemBuffer buffer) {
063: return new VerilogTagger(buffer);
064: }
065:
066: public boolean canIndent() {
067: return true;
068: }
069:
070: public int getCorrectIndentation(Line line, Buffer buffer) {
071: final int indentSize = buffer.getIndentSize();
072: final Line model = findModel(line);
073: if (model == null)
074: return 0;
075: final String trim = line.getText().trim();
076: final int modelIndent = buffer.getIndentation(model);
077: final String modelTrim = model.getText().trim();
078: if (line.flags() == STATE_COMMENT) {
079: if (modelTrim.startsWith("/*") && trim.startsWith("*"))
080: return modelIndent + 1;
081: else
082: return modelIndent;
083: }
084: if (modelTrim.endsWith("("))
085: return modelIndent + indentSize;
086: final String modelIdentifier = Utilities.getFirstIdentifier(
087: modelTrim, this );
088: if (Utilities.isOneOf(modelIdentifier, alwaysIndentAfter))
089: return modelIndent + indentSize;
090: if (Utilities.isOneOf(modelIdentifier, maybeIndentAfter)) {
091: if (modelTrim.endsWith(";"))
092: return modelIndent;
093: else
094: return modelIndent + indentSize;
095: }
096: final String identifier = Utilities.getFirstIdentifier(trim,
097: this );
098: if ("end".equals(identifier)) {
099: Line beginLine = findBeginLine(line);
100: if (beginLine != null)
101: return buffer.getIndentation(beginLine);
102: }
103: return modelIndent;
104: }
105:
106: private static Line findModel(Line line) {
107: Line model = line.previous();
108: if (line.flags() == STATE_COMMENT) {
109: // Any non-blank line is an acceptable model.
110: while (model != null && model.isBlank())
111: model = model.previous();
112: } else {
113: while (model != null && !isAcceptableModel(model))
114: model = model.previous();
115: }
116: return model;
117: }
118:
119: private static boolean isAcceptableModel(Line line) {
120: if (line.isBlank())
121: return false;
122: if (line.flags() == STATE_COMMENT)
123: return false;
124:
125: return true;
126: }
127:
128: private Line findBeginLine(Line line) {
129: int count = 1;
130: while (true) {
131: line = line.previous();
132: if (line == null)
133: return null;
134: String identifier = Utilities.getFirstIdentifier(line
135: .trim(), this );
136: if (identifier != null) {
137: if (identifier.equals("begin")) {
138: if (--count == 0)
139: return line;
140: } else if (identifier.equals("end"))
141: ++count;
142: }
143: }
144: }
145:
146: public boolean isIdentifierStart(char c) {
147: return startChars.indexOf(c) >= 0;
148: }
149:
150: public boolean isIdentifierPart(char c) {
151: return partChars.indexOf(c) >= 0;
152: }
153:
154: private static final String startChars = "`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_";
155:
156: private static final String partChars = "`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_$";
157:
158: private static final String[] alwaysIndentAfter = { "begin",
159: "case", "casex", "casez", "fork", "function", "generate",
160: "module", "primitive", "specify", "table", "task" };
161:
162: private static final String[] maybeIndentAfter = { "always",
163: "else", "for", "forever", "if", "initial", "repeat",
164: "while" };
165: }
|