001: package org.incava.javadoc;
002:
003: import java.awt.Point;
004: import java.util.ArrayList;
005: import java.util.List;
006:
007: /**
008: * Parses Javadoc into a list of points, which represent the locations of
009: * description and tagged comments in a Javadoc comment block.
010: */
011: public class JavadocParser {
012: /**
013: * The current position.
014: */
015: private int pos;
016:
017: /**
018: * The length of the Javadoc being parsed.
019: */
020: private int len;
021:
022: /**
023: * The Javadoc being parsed.
024: */
025: private String text;
026:
027: /**
028: * Parses the Javadoc in the text. Assumes a start line of 1 and a start
029: * column of 1.
030: */
031: public List parse(String text) {
032: return parse(text, 1, 1);
033: }
034:
035: public List parse(String text, int startLine, int startColumn) {
036: // tr.Ace.log("text", "+" + text + "+");
037:
038: this .text = text;
039:
040: len = text.length();
041: ArrayList ary = new ArrayList();
042: pos = 0;
043:
044: while (pos < len && Character.isWhitespace(text.charAt(pos))) {
045: ++pos;
046: }
047:
048: if (pos + 3 < len && text.startsWith("/**")) { // unmangle Emacs: */
049: // tr.Ace.log("got comment start");
050: pos += 3;
051:
052: while (pos < len
053: && (Character.isWhitespace(text.charAt(pos)) || text
054: .charAt(pos) == '*')) {
055: ++pos;
056: }
057:
058: --len;
059: while (len >= 0) {
060: // tr.Ace.log("char[" + len + "]: '" + text.charAt(len) + "'");
061: if (Character.isWhitespace(text.charAt(len))
062: || text.charAt(len) == '*') {
063: // tr.Ace.log("star or WS; (text: '" + text.charAt(len) + "')");
064: --len;
065: } else if (len > 0 && text.charAt(len) == '/'
066: && text.charAt(len - 1) == '*') {
067: // tr.Ace.log("at end of comment");
068: len -= 2;
069: } else {
070: break;
071: }
072: }
073: ++len;
074:
075: // tr.Ace.log("pos: " + pos + "; len: " + len);
076:
077: if (pos < len) {
078: // the description
079: if (text.charAt(pos) == '@') {
080: // tr.Ace.log("got tag start -- no description");
081: // null means no description
082: ary.add(null);
083: } else {
084: // tr.Ace.log("at description start: " + pos);
085:
086: Point desc = new Point(pos, -1);
087:
088: read(desc);
089:
090: // tr.Ace.log("at end, pos: " + pos + "; desc pos : " + desc);
091:
092: ary.add(desc);
093: }
094:
095: // now, the tagged comments:
096: while (pos < len && text.charAt(pos) == '@') {
097: // tr.Ace.log("tag starting.");
098:
099: Point tag = new Point(pos, -1);
100:
101: ++pos;
102: read(tag);
103:
104: // tr.Ace.log("tag pos : " + tag);
105:
106: ary.add(tag);
107: }
108: }
109:
110: // tr.Ace.log("returning: " + ary);
111:
112: return ary;
113: } else {
114: // tr.Ace.log("no Javadoc comment in this string.");
115: return null;
116: }
117: }
118:
119: /**
120: * Reads to the next Javadoc field, or to the end of the comment.
121: */
122: protected void read(Point pt) {
123: // tr.Ace.log("pos: " + pos + ", len: " + len + ", text: " + text + ", pt: " + pt);
124:
125: pt.y = pos;
126: while (pos < len
127: && (text.charAt(pos) != '@' || (pos >= 0 && text
128: .charAt(pos - 1) == '{'))) {
129: // // tr.Ace.log("pos: " + pos);
130: pt.y = pos;
131:
132: ++pos;
133:
134: // read to end of line, or end of text.
135: // Mac: \r, Unix: \n, DOS: \r\n:
136: if (text.charAt(pos) == '\r') {
137: if (pos + 1 < len && text.charAt(pos + 1) == '\n') {
138: ++pos;
139: }
140: } else if (text.charAt(pos) != '\n') {
141: continue;
142: }
143:
144: // tr.Ace.log("looking for next position");
145:
146: // now, we're at the start of a new line:
147: while (pos < len
148: && (Character.isWhitespace(text.charAt(pos)) || text
149: .charAt(pos) == '*')) {
150: ++pos;
151: // tr.Ace.log("advanced pos: " + pos);
152: }
153: }
154:
155: ++pt.y;
156: // tr.Ace.log("at end -- pos : " + pos + ", len: " + len + ", char: '" + text.charAt(pos) + "', text: " + text + ", pt: " + pt);
157: }
158:
159: }
|