001: package org.incava.text;
002:
003: import java.awt.Point;
004: import java.io.*;
005: import java.util.*;
006:
007: /**
008: * Converts from 0-indexed string positions to line:column values. Lines and
009: * columns are 1-indexed, matching the Java parser.
010: */
011: public class LineMapping extends ArrayList {
012: public class PositionToLocation {
013: public int position;
014:
015: public int line;
016:
017: public int column;
018:
019: public PositionToLocation(int position, int line, int column) {
020: this .position = position;
021: this .line = line;
022: this .column = column;
023: }
024:
025: public String toString() {
026: return "{ position: " + position + " => { line: " + line
027: + ", column: " + column + " } }";
028: }
029: }
030:
031: public LineMapping(String text, int startLine, int startColumn) {
032: // tr.Ace.log("position: " + 0 + " => { line: " + startLine + ", column: " + startColumn + " }");
033: add(new PositionToLocation(0, startLine, startColumn));
034:
035: int len = text.length();
036:
037: // figure out where the lines start:
038: for (int pos = 0, line = startLine; pos < len; ++pos) {
039: // Mac: \r, Unix: \n, DOS: \r\n
040: if (text.charAt(pos) == '\r') {
041: // might be DOS:
042: if (pos + 1 < len && text.charAt(pos + 1) == '\n') {
043: ++pos;
044: }
045: // otherwise, it's Mac (at least, before OS X)
046: } else if (text.charAt(pos) == '\n') {
047: // Unix
048: } else {
049: // we're not at a newline, so go to the next character.
050: continue;
051: }
052:
053: ++line;
054:
055: // tr.Ace.log("position: " + pos + " => { line: " + line + ", column: " + 1 + " }");
056: add(new PositionToLocation(pos + 1, line, 1));
057: }
058:
059: // tr.Ace.log("line positions: " + this);
060: }
061:
062: /**
063: * Converts the string position to a line:column start and end location.
064: */
065: public Location[] getLocations(Point pos) {
066: return getLocations(pos.x, pos.y);
067: }
068:
069: /**
070: * Converts the string position to a line:column start and end location.
071: */
072: public Location[] getLocations(int startPos, int endPos) {
073: // tr.Ace.log("parsing description");
074: Location start = null;
075: Location end = null;
076:
077: // tr.Ace.log("position: " + startPos + ", " + endPos);
078:
079: // go backward
080: ListIterator lit = listIterator(size());
081: while ((start == null || end == null) && lit.hasPrevious()) {
082: PositionToLocation pl = (PositionToLocation) lit.previous();
083: // tr.Ace.log("considering position/location " + pl);
084: if (end == null && endPos >= pl.position) {
085: // tr.Ace.log("assigning end");
086: end = new Location(pl.line, pl.column + endPos
087: - pl.position);
088: }
089: if (start == null && startPos >= pl.position) {
090: // tr.Ace.log("assigning start");
091: start = new Location(pl.line, pl.column + startPos
092: - pl.position);
093: }
094: }
095:
096: // attn Sun: tuples, please!
097: return new Location[] { start, end };
098: }
099:
100: /**
101: * Converts the string position to a line:column location.
102: */
103: public Location getLocation(int pos) {
104: Location location = null;
105:
106: // tr.Ace.log("position: " + pos);
107:
108: // go backward
109: ListIterator lit = listIterator(size());
110: while (location == null && lit.hasPrevious()) {
111: PositionToLocation pl = (PositionToLocation) lit.previous();
112: // tr.Ace.log("considering position/location " + pl);
113: if (location == null && pos >= pl.position) {
114: // tr.Ace.log("creating location");
115: return new Location(pl.line, pl.column + pos
116: - pl.position);
117: }
118: }
119:
120: return null;
121: }
122:
123: }
|