diff --git a/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/IParser.java b/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/IParser.java index 98d239ede5e46101d8dba291da5637716943996c..1dcb9585ca7d56d0f5352788fcb05cc1f424da6b 100644 --- a/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/IParser.java +++ b/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/IParser.java @@ -10,5 +10,5 @@ import java.util.Map; public interface IParser { - public Map<PositionedNode, SourcecodeRange> getMapping(); + public Map<PositionedNode, SourcecodeRange> getMapping(); } diff --git a/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/IToken.java b/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/IToken.java index b8ae5da99d66db0636daa871541e0a558e245a06..7dfa0e4cc498024c02d3c49f58cd222e8f063819 100644 --- a/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/IToken.java +++ b/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/IToken.java @@ -9,15 +9,15 @@ package de.hhu.stups.sablecc.patch; public interface IToken { - public String getText(); + public String getText(); - public void setText(String text); + public void setText(String text); - public int getLine(); + public int getLine(); - public void setLine(int line); + public void setLine(int line); - public int getPos(); + public int getPos(); - public void setPos(int pos); + public void setPos(int pos); } diff --git a/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/ITokenListContainer.java b/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/ITokenListContainer.java index 8280e1e0f0eb1727adc5e0011eb4a633d9655e96..eb5eb885b4944beaa8dc15105ac33a0b8c2a7670 100644 --- a/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/ITokenListContainer.java +++ b/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/ITokenListContainer.java @@ -9,5 +9,5 @@ package de.hhu.stups.sablecc.patch; import java.util.List; public interface ITokenListContainer { - public List<IToken> getTokenList(); + public List<IToken> getTokenList(); } diff --git a/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/PositionedNode.java b/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/PositionedNode.java index 0af0ce91b157cf7ed18aa3d8d1a7c8d26221e773..d26abd46336d98e28e3785e8858d9987bc5b897f 100644 --- a/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/PositionedNode.java +++ b/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/PositionedNode.java @@ -7,41 +7,41 @@ package de.hhu.stups.sablecc.patch; public class PositionedNode { - private SourcePosition startPos; - private SourcePosition endPos; - - public SourcePosition getStartPos() { - /* - * Special treatment for tokens because they don't get a position in the - * PositionAspect - */ - if (this instanceof IToken) { - final IToken token = (IToken) this; - return new SourcePosition(token.getLine(), token.getPos()); - } - - return startPos; - } - - public SourcePosition getEndPos() { - /* - * Special treatment for tokens because they don't get a position in the - * PositionAspect - */ - if (this instanceof IToken) { - final IToken token = (IToken) this; - return new SourcePosition(token.getLine(), token.getPos() - + token.getText().length()); - } - - return endPos; - } - - public void setStartPos(final SourcePosition startPos) { - this.startPos = startPos; - } - - public void setEndPos(final SourcePosition endPos) { - this.endPos = endPos; - } + private SourcePosition startPos; + private SourcePosition endPos; + + public SourcePosition getStartPos() { + /* + * Special treatment for tokens because they don't get a position in the + * PositionAspect + */ + if (this instanceof IToken) { + final IToken token = (IToken) this; + return new SourcePosition(token.getLine(), token.getPos()); + } + + return startPos; + } + + public SourcePosition getEndPos() { + /* + * Special treatment for tokens because they don't get a position in the + * PositionAspect + */ + if (this instanceof IToken) { + final IToken token = (IToken) this; + return new SourcePosition(token.getLine(), token.getPos() + + token.getText().length()); + } + + return endPos; + } + + public void setStartPos(final SourcePosition startPos) { + this.startPos = startPos; + } + + public void setEndPos(final SourcePosition endPos) { + this.endPos = endPos; + } } diff --git a/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/SourcePosition.java b/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/SourcePosition.java index 106966f010635c84e4a32c81354579359662a43f..2b3451b2d6d91a1c6475f6f96fc9c6cddbdcf40e 100644 --- a/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/SourcePosition.java +++ b/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/SourcePosition.java @@ -8,33 +8,33 @@ package de.hhu.stups.sablecc.patch; public class SourcePosition implements Comparable<SourcePosition> { - private final int line; + private final int line; - private final int pos; + private final int pos; - public SourcePosition(final int line, final int pos) { - this.line = line; - this.pos = pos; - } + public SourcePosition(final int line, final int pos) { + this.line = line; + this.pos = pos; + } - public int getLine() { - return line; - } + public int getLine() { + return line; + } - public int getPos() { - return pos; - } - - public int compareTo(SourcePosition that) { - if (that.line < line) return 1; - if (that.line > line) return -1; - return pos-that.pos; - } - - @Override - public String toString() { - return "(" + line + "," + pos + ")"; - } - - + public int getPos() { + return pos; + } + + public int compareTo(SourcePosition that) { + if (that.line < line) return 1; + if (that.line > line) return -1; + return pos-that.pos; + } + + @Override + public String toString() { + return "(" + line + "," + pos + ")"; + } + + } diff --git a/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/SourcePositions.java b/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/SourcePositions.java index a13acd004bf59fe8ccb7bf884e6dc5f4d2585859..0c30041a68683e38cffc6399ab07abad7f4a570f 100644 --- a/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/SourcePositions.java +++ b/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/SourcePositions.java @@ -11,422 +11,422 @@ import java.util.List; import java.util.Map; public class SourcePositions { - private final List<IToken> tokenList; - private final Map<PositionedNode, SourcecodeRange> positions; - - public SourcePositions(final List<IToken> tokenList, - final Map<PositionedNode, SourcecodeRange> positions) { - this.tokenList = tokenList; - this.positions = positions; - } - - /** - * Returns the {@link SourcecodeRange} of this {@link PositionedNode} or - * {@code null} if no {@link SourcecodeRange} is available. - * - * @param node the node with source code information - * @return the source code range of {@code node} - */ - public SourcecodeRange getSourcecodeRange(final PositionedNode node) { - return positions.get(node); - } - - /** - * Returns the line in which this {@link PositionedNode} begins. The value - * {@code 0} is returned if no sourcecode range is available for this - * {@link PositionedNode}. - * - * @param node the node with source code information - * @return the line where the {@code node} starts - */ - public int getBeginLine(final PositionedNode node) { - if (node instanceof IToken) { - return ((IToken) node).getLine(); - } - - return getBeginLine(getSourcecodeRange(node)); - } - - public int getBeginLine(final SourcecodeRange range) { - if (range != null) { - return tokenList.get(range.getBeginIndex()).getLine(); - } else { - return 0; - } - } - - /** - * Returns the column of the first character of this {@link PositionedNode}, - * i.e. the begin column. The value {@code 0} is returned if no - * sourcecode range is available for this {@link PositionedNode}. - * - * @param node the node with source code information - * @return the begin column of {@code node} - */ - public int getBeginColumn(final PositionedNode node) { - if (node instanceof IToken) { - return ((IToken) node).getPos(); - } - - return getBeginColumn(getSourcecodeRange(node)); - } - - public int getBeginColumn(final SourcecodeRange range) { - if (range != null) { - return tokenList.get(range.getBeginIndex()).getPos(); - } else { - return 0; - } - } - - /** - * Returns the line in which the {@link PositionedNode} ends. The value - * {@code 0} is returned if no sourcecode range is available for this - * {@link PositionedNode}. - * - * @param node the node with source code information - * @return the end line of <code>node</code> - */ - public int getEndLine(final PositionedNode node) { - // TODO handle multi line comments - /* - * if (node instanceof TComment) { final TComment comment = (TComment) - * node; return comment.getLine() + countLineBreaks(comment); } - */ - - if (node instanceof IToken) { - return ((IToken) node).getLine(); - } - - return getEndLine(getSourcecodeRange(node)); - } - - private int getEndLine(final SourcecodeRange range) { - if (range != null) { - return tokenList.get(range.getEndIndex()).getLine(); - } else { - return 0; - } - } - - // private int countLineBreaks(final PositionedNode node) { - // final char[] text = getNodeString(node).toCharArray(); - // int count = 0; - // - // for (int i = 0; i < text.length; i++) { - // if (text[i] == '\n' || text[i] == '\r') { - // count++; - // } - // } - // - // return count; - // } - - /** - * Returns the last column of this {@link PositionedNode}, i.e. the column - * of the last character of the {@link PositionedNode}. The value - * {@code 0} is returned if no sourcecode range is available for this - * {@link PositionedNode}. - * - * @param node the node with source code information - * @return the end column of <code>node</code> - */ - public int getEndColumn(final PositionedNode node) { - // TODO handle multi line comments - /* - * if (node instanceof TComment) { return getEndColumn((TComment) node); - * } - */ - - if (node instanceof IToken) { - final IToken token = (IToken) node; - return token.getPos() + token.getText().length() - 1; - } - - return getEndColumn(getSourcecodeRange(node)); - } - - private int getEndColumn(final SourcecodeRange range) { - if (range != null) { - final IToken token = tokenList.get(range.getEndIndex()); - return token.getPos() + token.getText().length() - 1; - } else { - return 0; - } - } - - /* - * private int getEndColumn(final TComment commentToken) { final String - * asString = commentToken.getText(); final StringTokenizer tokenizer = new - * StringTokenizer(asString, "\n\r"); - * - * // multi line comment if (tokenizer.countTokens() > 1) { String line = - * null; while (tokenizer.hasMoreTokens()) { line = tokenizer.nextToken(); } - * - * if (line == null) { return 0; } - * - * return line.length(); } // single line comment else { return - * commentToken.getPos() + asString.length(); } } - */ - - /** - * Returns the array of {@link IToken}s belonging to this - * {@link PositionedNode}. The array may be empty, if no sourcecode range - * can be determined for this {@link PositionedNode}. - * - * @param node the node with source code information - * @return all tokens of {@code node} - */ - public IToken[] getTokens(final PositionedNode node) { - if (node instanceof IToken) { - return new IToken[] { (IToken) node }; - } - - final SourcecodeRange range = getSourcecodeRange(node); - - if (range != null) { - final int beginIndex = range.getBeginIndex(); - final int endIndex = range.getEndIndex(); - final IToken[] result = new IToken[endIndex - beginIndex + 1]; - - for (int i = 0; i + beginIndex <= endIndex; i++) { - result[i] = tokenList.get(i + beginIndex); - } - - return result; - } else { - return new IToken[0]; - } - } - - public String getNodeString(final PositionedNode node) { - // TODO handle comments - /* - * if (node instanceof TComment) { return ((TComment) node).getText(); } - */ - - return getRangeString(getSourcecodeRange(node)); - } - - public String getRangeString(final SourcecodeRange range) { - final StringBuilder buffer = new StringBuilder(); - - if (range != null) { - final int beginIndex = range.getBeginIndex(); - final int endIndex = range.getEndIndex(); - - for (int i = beginIndex; i <= endIndex; i++) { - buffer.append(tokenList.get(i).getText()); - } - } - - return buffer.toString(); - } - - // TODO handle comments - /* - * - * public IToken getCommentBefore(final PositionedNode node) { final - * SourcecodeRange range = getSourcecodeRange(node); final int beginIndex = - * range.getBeginIndex(); if (beginIndex > 0) { final IToken token = - * tokenList.get(beginIndex - 1); if (token instanceof TComment) { return - * token; } else { return null; } } else { return null; } } - * - * public IToken getCommentAfter(final PositionedNode node) { final - * SourcecodeRange range = getSourcecodeRange(node); final int endIndex = - * range.getEndIndex(); if (endIndex < tokenList.size() - 1) { final IToken - * token = tokenList.get(endIndex + 1); if (token instanceof TComment) { - * return token; } else { return null; } } else { return null; } } public - * IToken[] getIncludedComments(final PositionedNode node) { final - * SourcecodeRange range = getSourcecodeRange(node); - * - * if (range != null) { final int beginIndex = range.getBeginIndex(); final - * int endIndex = range.getEndIndex(); final List<IToken> comments = new - * ArrayList<IToken>(); - * - * for (int i = 0; i + beginIndex <= endIndex; i++) { final IToken token = - * tokenList.get(i + beginIndex); if (token instanceof TComment) { - * comments.add(token); } } - * - * return comments.toArray(new IToken[comments.size()]); } else { return new - * IToken[0]; } } - */ - - public List<IToken> getTokenList() { - return tokenList; - } - - public void replaceMapping(final PositionedNode origNode, - final PositionedNode newNode) { - final SourcecodeRange sourcecodeRange = positions.remove(origNode); - - if (sourcecodeRange != null) { - positions.put(newNode, sourcecodeRange); - } - } - - public PositionedNode getSurroundingNode(final int index) { - if (index < 0 || index >= tokenList.size()) { - return null; - } - - PositionedNode bestNode = null; - int bestBeginIndex = 0; - int bestEndIndex = tokenList.size() - 1; - - // TODO find better solution than searching all? - for (final Iterator<PositionedNode> iterator = positions.keySet() - .iterator(); iterator.hasNext();) { - final PositionedNode node = iterator.next(); - final SourcecodeRange range = positions.get(node); - - final int beginIndex = range.getBeginIndex(); - final int endIndex = range.getEndIndex(); - - if (beginIndex <= index && endIndex >= index - && beginIndex >= bestBeginIndex && endIndex <= bestEndIndex) { - bestNode = node; - bestBeginIndex = beginIndex; - bestEndIndex = endIndex; - } - } - - return bestNode; - } - - /** - * <p> - * Finds the index of the token that belongs to the position. - * </p> - * <p> - * If no token list is available {@code -1} is returned. For - * {@code line < 0} the index {@code 0} is returned. If - * {@code line >= 1 && column < 0} the line number is returned. - * </p> - * <p> - * If the line matches but the requested column is beyond the max. length of - * the line, the last token of this line is returned. The last token of all - * tokens (EOF) is chosen if the requested positions is beyond the - * absolutely last token. - * </p> - * <p> - * <b>Attention</b>: Line and column counting starts at 1! - * </p> - * - * @param line - * line of the position - * @param column - * column of the position - * @return Index in {@link #tokenList} - */ - public int getTokenforPosition(final int line, final int column) { - // Sort out nonsense input - if (tokenList.size() == 0) { - return -1; - } - if (line < 1) { - return 0; - } - if (column < 1) { - return line; - } - - /* - * Shortcut for special case: Position beyond last token - */ - final IToken lastToken = tokenList.get(tokenList.size() - 1); - if (line > lastToken.getLine() - || (line == lastToken.getLine() && column > lastToken.getPos() - + lastToken.getText().length())) { - return tokenList.size() - 1; - } - - int result = -1; - int left = 0; - int right = tokenList.size() - 1; - - while (left <= right && result < 0) { - if (left != right) { - final int currentIndex = left + (right - left) / 2; - - final int lineDiff = line - - tokenList.get(currentIndex).getLine(); - - if (lineDiff > 0) { - // continue in right half - left = Math.min(currentIndex + 1, right); - } else if (lineDiff < 0) { - // continue in left half - right = Math.max(currentIndex - 1, left); - } else { - // we are in the correct line now, switch to linear search - IToken token = tokenList.get(currentIndex); - result = currentIndex; - - final int compare = compareTokenColumn(token, column); - - // move left - if (compare < 0) { - while (compareTokenColumn(token, column) < 0) { - result--; - - if (result < 0) { - break; - } - - token = tokenList.get(result); - } - } - // move right - else if (compare > 0) { - while (compareTokenColumn(token, column) > 0) { - result++; - - if (result > tokenList.size() - 1) { - result = tokenList.size() - 1; - break; - } - - token = tokenList.get(result); - - /* - * Only move as long as line end is not reached. - * This happens when queried for column beyond max - * column of this line. Then we return the index of - * the last token in this line. - */ - if (token.getLine() > line) { - result--; - break; - } - } - } - } - } else { - result = left; - } - } - - return result; - } - - /** - * Compares the token position (within line only) with the column. - * - * @return {@code -1} if {@code column < beginColumn}, - * {@code 1} if {@code endColumn < column} or - * {@code 0} if the column is within the range of the token. - */ - private int compareTokenColumn(final IToken token, final int column) { - final int beginColumn = token.getPos(); - final int endColumn = beginColumn + token.getText().length() - 1; - - if (column < beginColumn) { - return -1; - } else if (endColumn < column) { - return 1; - } else { - return 0; - } - } + private final List<IToken> tokenList; + private final Map<PositionedNode, SourcecodeRange> positions; + + public SourcePositions(final List<IToken> tokenList, + final Map<PositionedNode, SourcecodeRange> positions) { + this.tokenList = tokenList; + this.positions = positions; + } + + /** + * Returns the {@link SourcecodeRange} of this {@link PositionedNode} or + * {@code null} if no {@link SourcecodeRange} is available. + * + * @param node the node with source code information + * @return the source code range of {@code node} + */ + public SourcecodeRange getSourcecodeRange(final PositionedNode node) { + return positions.get(node); + } + + /** + * Returns the line in which this {@link PositionedNode} begins. The value + * {@code 0} is returned if no sourcecode range is available for this + * {@link PositionedNode}. + * + * @param node the node with source code information + * @return the line where the {@code node} starts + */ + public int getBeginLine(final PositionedNode node) { + if (node instanceof IToken) { + return ((IToken) node).getLine(); + } + + return getBeginLine(getSourcecodeRange(node)); + } + + public int getBeginLine(final SourcecodeRange range) { + if (range != null) { + return tokenList.get(range.getBeginIndex()).getLine(); + } else { + return 0; + } + } + + /** + * Returns the column of the first character of this {@link PositionedNode}, + * i.e. the begin column. The value {@code 0} is returned if no + * sourcecode range is available for this {@link PositionedNode}. + * + * @param node the node with source code information + * @return the begin column of {@code node} + */ + public int getBeginColumn(final PositionedNode node) { + if (node instanceof IToken) { + return ((IToken) node).getPos(); + } + + return getBeginColumn(getSourcecodeRange(node)); + } + + public int getBeginColumn(final SourcecodeRange range) { + if (range != null) { + return tokenList.get(range.getBeginIndex()).getPos(); + } else { + return 0; + } + } + + /** + * Returns the line in which the {@link PositionedNode} ends. The value + * {@code 0} is returned if no sourcecode range is available for this + * {@link PositionedNode}. + * + * @param node the node with source code information + * @return the end line of <code>node</code> + */ + public int getEndLine(final PositionedNode node) { + // TODO handle multi line comments + /* + * if (node instanceof TComment) { final TComment comment = (TComment) + * node; return comment.getLine() + countLineBreaks(comment); } + */ + + if (node instanceof IToken) { + return ((IToken) node).getLine(); + } + + return getEndLine(getSourcecodeRange(node)); + } + + private int getEndLine(final SourcecodeRange range) { + if (range != null) { + return tokenList.get(range.getEndIndex()).getLine(); + } else { + return 0; + } + } + + // private int countLineBreaks(final PositionedNode node) { + // final char[] text = getNodeString(node).toCharArray(); + // int count = 0; + // + // for (int i = 0; i < text.length; i++) { + // if (text[i] == '\n' || text[i] == '\r') { + // count++; + // } + // } + // + // return count; + // } + + /** + * Returns the last column of this {@link PositionedNode}, i.e. the column + * of the last character of the {@link PositionedNode}. The value + * {@code 0} is returned if no sourcecode range is available for this + * {@link PositionedNode}. + * + * @param node the node with source code information + * @return the end column of <code>node</code> + */ + public int getEndColumn(final PositionedNode node) { + // TODO handle multi line comments + /* + * if (node instanceof TComment) { return getEndColumn((TComment) node); + * } + */ + + if (node instanceof IToken) { + final IToken token = (IToken) node; + return token.getPos() + token.getText().length() - 1; + } + + return getEndColumn(getSourcecodeRange(node)); + } + + private int getEndColumn(final SourcecodeRange range) { + if (range != null) { + final IToken token = tokenList.get(range.getEndIndex()); + return token.getPos() + token.getText().length() - 1; + } else { + return 0; + } + } + + /* + * private int getEndColumn(final TComment commentToken) { final String + * asString = commentToken.getText(); final StringTokenizer tokenizer = new + * StringTokenizer(asString, "\n\r"); + * + * // multi line comment if (tokenizer.countTokens() > 1) { String line = + * null; while (tokenizer.hasMoreTokens()) { line = tokenizer.nextToken(); } + * + * if (line == null) { return 0; } + * + * return line.length(); } // single line comment else { return + * commentToken.getPos() + asString.length(); } } + */ + + /** + * Returns the array of {@link IToken}s belonging to this + * {@link PositionedNode}. The array may be empty, if no sourcecode range + * can be determined for this {@link PositionedNode}. + * + * @param node the node with source code information + * @return all tokens of {@code node} + */ + public IToken[] getTokens(final PositionedNode node) { + if (node instanceof IToken) { + return new IToken[] { (IToken) node }; + } + + final SourcecodeRange range = getSourcecodeRange(node); + + if (range != null) { + final int beginIndex = range.getBeginIndex(); + final int endIndex = range.getEndIndex(); + final IToken[] result = new IToken[endIndex - beginIndex + 1]; + + for (int i = 0; i + beginIndex <= endIndex; i++) { + result[i] = tokenList.get(i + beginIndex); + } + + return result; + } else { + return new IToken[0]; + } + } + + public String getNodeString(final PositionedNode node) { + // TODO handle comments + /* + * if (node instanceof TComment) { return ((TComment) node).getText(); } + */ + + return getRangeString(getSourcecodeRange(node)); + } + + public String getRangeString(final SourcecodeRange range) { + final StringBuilder buffer = new StringBuilder(); + + if (range != null) { + final int beginIndex = range.getBeginIndex(); + final int endIndex = range.getEndIndex(); + + for (int i = beginIndex; i <= endIndex; i++) { + buffer.append(tokenList.get(i).getText()); + } + } + + return buffer.toString(); + } + + // TODO handle comments + /* + * + * public IToken getCommentBefore(final PositionedNode node) { final + * SourcecodeRange range = getSourcecodeRange(node); final int beginIndex = + * range.getBeginIndex(); if (beginIndex > 0) { final IToken token = + * tokenList.get(beginIndex - 1); if (token instanceof TComment) { return + * token; } else { return null; } } else { return null; } } + * + * public IToken getCommentAfter(final PositionedNode node) { final + * SourcecodeRange range = getSourcecodeRange(node); final int endIndex = + * range.getEndIndex(); if (endIndex < tokenList.size() - 1) { final IToken + * token = tokenList.get(endIndex + 1); if (token instanceof TComment) { + * return token; } else { return null; } } else { return null; } } public + * IToken[] getIncludedComments(final PositionedNode node) { final + * SourcecodeRange range = getSourcecodeRange(node); + * + * if (range != null) { final int beginIndex = range.getBeginIndex(); final + * int endIndex = range.getEndIndex(); final List<IToken> comments = new + * ArrayList<IToken>(); + * + * for (int i = 0; i + beginIndex <= endIndex; i++) { final IToken token = + * tokenList.get(i + beginIndex); if (token instanceof TComment) { + * comments.add(token); } } + * + * return comments.toArray(new IToken[comments.size()]); } else { return new + * IToken[0]; } } + */ + + public List<IToken> getTokenList() { + return tokenList; + } + + public void replaceMapping(final PositionedNode origNode, + final PositionedNode newNode) { + final SourcecodeRange sourcecodeRange = positions.remove(origNode); + + if (sourcecodeRange != null) { + positions.put(newNode, sourcecodeRange); + } + } + + public PositionedNode getSurroundingNode(final int index) { + if (index < 0 || index >= tokenList.size()) { + return null; + } + + PositionedNode bestNode = null; + int bestBeginIndex = 0; + int bestEndIndex = tokenList.size() - 1; + + // TODO find better solution than searching all? + for (final Iterator<PositionedNode> iterator = positions.keySet() + .iterator(); iterator.hasNext();) { + final PositionedNode node = iterator.next(); + final SourcecodeRange range = positions.get(node); + + final int beginIndex = range.getBeginIndex(); + final int endIndex = range.getEndIndex(); + + if (beginIndex <= index && endIndex >= index + && beginIndex >= bestBeginIndex && endIndex <= bestEndIndex) { + bestNode = node; + bestBeginIndex = beginIndex; + bestEndIndex = endIndex; + } + } + + return bestNode; + } + + /** + * <p> + * Finds the index of the token that belongs to the position. + * </p> + * <p> + * If no token list is available {@code -1} is returned. For + * {@code line < 0} the index {@code 0} is returned. If + * {@code line >= 1 && column < 0} the line number is returned. + * </p> + * <p> + * If the line matches but the requested column is beyond the max. length of + * the line, the last token of this line is returned. The last token of all + * tokens (EOF) is chosen if the requested positions is beyond the + * absolutely last token. + * </p> + * <p> + * <b>Attention</b>: Line and column counting starts at 1! + * </p> + * + * @param line + * line of the position + * @param column + * column of the position + * @return Index in {@link #tokenList} + */ + public int getTokenforPosition(final int line, final int column) { + // Sort out nonsense input + if (tokenList.size() == 0) { + return -1; + } + if (line < 1) { + return 0; + } + if (column < 1) { + return line; + } + + /* + * Shortcut for special case: Position beyond last token + */ + final IToken lastToken = tokenList.get(tokenList.size() - 1); + if (line > lastToken.getLine() + || (line == lastToken.getLine() && column > lastToken.getPos() + + lastToken.getText().length())) { + return tokenList.size() - 1; + } + + int result = -1; + int left = 0; + int right = tokenList.size() - 1; + + while (left <= right && result < 0) { + if (left != right) { + final int currentIndex = left + (right - left) / 2; + + final int lineDiff = line + - tokenList.get(currentIndex).getLine(); + + if (lineDiff > 0) { + // continue in right half + left = Math.min(currentIndex + 1, right); + } else if (lineDiff < 0) { + // continue in left half + right = Math.max(currentIndex - 1, left); + } else { + // we are in the correct line now, switch to linear search + IToken token = tokenList.get(currentIndex); + result = currentIndex; + + final int compare = compareTokenColumn(token, column); + + // move left + if (compare < 0) { + while (compareTokenColumn(token, column) < 0) { + result--; + + if (result < 0) { + break; + } + + token = tokenList.get(result); + } + } + // move right + else if (compare > 0) { + while (compareTokenColumn(token, column) > 0) { + result++; + + if (result > tokenList.size() - 1) { + result = tokenList.size() - 1; + break; + } + + token = tokenList.get(result); + + /* + * Only move as long as line end is not reached. + * This happens when queried for column beyond max + * column of this line. Then we return the index of + * the last token in this line. + */ + if (token.getLine() > line) { + result--; + break; + } + } + } + } + } else { + result = left; + } + } + + return result; + } + + /** + * Compares the token position (within line only) with the column. + * + * @return {@code -1} if {@code column < beginColumn}, + * {@code 1} if {@code endColumn < column} or + * {@code 0} if the column is within the range of the token. + */ + private int compareTokenColumn(final IToken token, final int column) { + final int beginColumn = token.getPos(); + final int endColumn = beginColumn + token.getText().length() - 1; + + if (column < beginColumn) { + return -1; + } else if (endColumn < column) { + return 1; + } else { + return 0; + } + } } diff --git a/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/SourcecodeRange.java b/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/SourcecodeRange.java index e064a453a08f4bdbefe9fe4f79e199b1e5be1858..7f25cd153241510857a2e3f7b3ae2681ab35e8c9 100644 --- a/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/SourcecodeRange.java +++ b/sablecc-runtime/src/main/java/de/hhu/stups/sablecc/patch/SourcecodeRange.java @@ -7,24 +7,24 @@ package de.hhu.stups.sablecc.patch; public class SourcecodeRange { - private final int beginIndex; - private final int endIndex; + private final int beginIndex; + private final int endIndex; - public SourcecodeRange(final int beginIndex, final int endIndex) { - this.beginIndex = beginIndex; - this.endIndex = endIndex; - } + public SourcecodeRange(final int beginIndex, final int endIndex) { + this.beginIndex = beginIndex; + this.endIndex = endIndex; + } - public int getBeginIndex() { - return beginIndex; - } + public int getBeginIndex() { + return beginIndex; + } - public int getEndIndex() { - return endIndex; - } + public int getEndIndex() { + return endIndex; + } - @Override - public String toString() { - return "(" + beginIndex + "/" + endIndex + ")"; - } + @Override + public String toString() { + return "(" + beginIndex + "/" + endIndex + ")"; + } } diff --git a/src/main/java/org/sablecc/sablecc/Inlining.java b/src/main/java/org/sablecc/sablecc/Inlining.java index 35a4fa9d11eadbaf3cd7096a1fd26faed21a7b09..906808e0d92746585d585c1b868a5bcedbbcd2eb 100644 --- a/src/main/java/org/sablecc/sablecc/Inlining.java +++ b/src/main/java/org/sablecc/sablecc/Inlining.java @@ -163,7 +163,7 @@ public class Inlining LinkedList listOfElems = new TypedLinkedList(StringCast.instance); for(int j=0; j<arrayOfElems.length; j++) { - listOfElems.add(arrayOfElems[j].getId().getText()); + listOfElems.add(arrayOfElems[j].getId().getText()); } theWhole[i] = listOfElems; diff --git a/src/main/java/org/sablecc/sablecc/InternalTransformationsToGrammar.java b/src/main/java/org/sablecc/sablecc/InternalTransformationsToGrammar.java index cf2fb0f3999d421d05e63a903f5d55c2b2429052..778421d712db550a73d025a71c10d2a447cde2bb 100644 --- a/src/main/java/org/sablecc/sablecc/InternalTransformationsToGrammar.java +++ b/src/main/java/org/sablecc/sablecc/InternalTransformationsToGrammar.java @@ -452,9 +452,9 @@ public class InternalTransformationsToGrammar extends DepthFirstAdapter This creates the production :: $elem {-> elem* } - = {nonTerminal} $elem elem {-> [$elem.elem elem] } - | {terminal} elem {-> [elem] } - ; + = {nonTerminal} $elem elem {-> [$elem.elem elem] } + | {terminal} elem {-> [elem] } + ; */ public AProd createXelemProduction(final String name, final String elemTypeName, String XproductionName, diff --git a/src/main/java/org/sablecc/sablecc/SableCC.java b/src/main/java/org/sablecc/sablecc/SableCC.java index 88445dba950fbca8ba7501bcc98b9c08a11d7ffb..5d7ba93dd0def24bb94cbd37e3035782d7b64090 100644 --- a/src/main/java/org/sablecc/sablecc/SableCC.java +++ b/src/main/java/org/sablecc/sablecc/SableCC.java @@ -17,255 +17,255 @@ import org.sablecc.sablecc.parser.*; import java.util.Vector; public class SableCC { - private static boolean processInlining = true; - static int inliningMaxAlts = 20; - private static boolean prettyPrinting = false; - - private static final String OPT_LICENSE = "--license"; - private static final String OPT_D = "-d"; - private static final String OPT_NO_INLINE = "--no-inline"; - private static final String OPT_INLINE_MAX_ALTS = "--inline-max-alts"; - private static final String OPT_PRETTY_PRINT = "--pretty-print"; - - private static void displayCopyright() { - System.out.println(); - System.out.println("SableCC version " + Version.VERSION - + " HHU Version"); - System.out - .println("Copyright (C) 1997-2003 Etienne M. Gagnon <etienne.gagnon@uqam.ca> and"); - System.out.println("others. All rights reserved."); - System.out.println(); - System.out - .println("This software comes with ABSOLUTELY NO WARRANTY. This is free software,"); - System.out - .println("and you are welcome to redistribute it under certain conditions."); - System.out.println(); - System.out.println("Type 'sablecc -license' to view"); - System.out.println("the complete copyright notice and license."); - System.out.println(); - } - - private static void displayUsage() { - System.out.println("Usage:"); - System.out.println(" sablecc [" + OPT_D + " destination] [" - + OPT_NO_INLINE + "] [" + OPT_INLINE_MAX_ALTS + " number] [" - + OPT_PRETTY_PRINT + "] filename [filename]..."); - System.out.println(" sablecc " + OPT_LICENSE); - } - - public static void main(String[] arguments) { - String d_option = null; - Vector<String> filename = new Vector<>(); - - if (arguments.length == 0) { - displayCopyright(); - displayUsage(); - System.exit(1); - } - - if ((arguments.length == 1) && (arguments[0].equals(OPT_LICENSE))) { - new DisplayLicense(); - System.exit(0); - } - - displayCopyright(); - - { - int arg = 0; - while (arg < arguments.length) { - if (arguments[arg].equals(OPT_D)) { - if ((d_option == null) && (++arg < arguments.length)) { - d_option = arguments[arg]; - } else { - displayUsage(); - System.exit(1); - } - } else if (arguments[arg].equals(OPT_NO_INLINE)) { - processInlining = false; - } - /* - * A production is not inlined if it has more than - * inliningMaxAlts alternatives. The default value is 20. - */ - else if (arguments[arg].equals(OPT_INLINE_MAX_ALTS)) { - try { - inliningMaxAlts = Integer.parseInt(arguments[++arg]); - } catch (Exception e) { - displayUsage(); - System.exit(1); - } - } - /* - * if prettyprint flag is set to true, only the transformed - * grammar is printed on standard output - */ - else if (arguments[arg].equals(OPT_PRETTY_PRINT)) { - prettyPrinting = true; - } else { - filename.addElement(arguments[arg]); - } - arg++; - } - - if (filename.size() == 0) { - displayUsage(); - System.exit(1); - } - } - - try { - for (int i = 0; i < filename.size(); i++) { - processGrammar(filename.elementAt(i), d_option); - } - } catch (Exception e) { - e.printStackTrace(); - System.exit(1); - } - System.exit(0); - } - - /** - * The main method for processing grammar file and generating the - * parser/lexer. - * - * @param grammar - * input grammar file name - * @param destDir - * output directory name - */ - public static void processGrammar(String grammar, String destDir) - throws Exception { - File in; - File dir; - - in = new File(grammar); - in = new File(in.getAbsolutePath()); - - if (destDir == null) { - dir = new File(in.getParent()); - } else { - dir = new File(destDir); - dir = new File(dir.getAbsolutePath()); - } - - processGrammar(in, dir); - } - - /** - * The main method for processing grammar file and generating the - * parser/lexer. - * - * @param in - * input grammar file - * @param dir - * output directory - */ - public static void processGrammar(File in, File dir) throws Exception { - if (!in.exists()) { - System.out.println("ERROR: grammar file " + in.getName() - + " does not exist."); - System.exit(1); - } - if (!dir.exists()) { - System.out.println("ERROR: destination directory " + dir.getName() - + " does not exist."); - System.exit(1); - } - - // re-initialize all static structures in the engine - LR0Collection.reinit(); - Symbol.reinit(); - Production.reinit(); - Grammar.reinit(); - - System.out.println("\n -- Generating parser for " + in.getName() - + " in " + dir.getPath()); - - FileReader temp = new FileReader(in); - - // Build the AST - Start tree = new Parser(new Lexer(new PushbackReader( - temp = new FileReader(in), 1000))).parse(); - - temp.close(); - - boolean hasTransformations = false; - - if (((AGrammar) tree.getPGrammar()).getAst() == null) { - System.out - .println("Adding productions and alternative of section AST."); - // AddAstProductions astProductions = new AddAstProductions(); - tree.apply(new AddAstProductions()); - } else { - hasTransformations = true; - } - - System.out.println("Verifying identifiers."); - ResolveIds ids = new ResolveIds(dir); - tree.apply(ids); - - System.out.println("Verifying ast identifiers."); - ResolveAstIds ast_ids = new ResolveAstIds(ids); - tree.apply(ast_ids); - - System.out - .println("Adding empty productions and empty alternative transformation if necessary."); - tree.apply(new AddEventualEmptyTransformationToProductions(ids, ast_ids)); - - System.out - .println("Adding productions and alternative transformation if necessary."); - AddProdTransformAndAltTransform adds = new AddProdTransformAndAltTransform(); - tree.apply(adds); - /* - * System.out.println( - * "Replacing AST + operator by * and removing ? operator if necessary" - * ); tree.apply( new AstTransformations() ); - */ - System.out.println("computing alternative symbol table identifiers."); - ResolveAltIds alt_ids = new ResolveAltIds(ids); - tree.apply(alt_ids); - - System.out.println("Verifying production transform identifiers."); - ResolveProdTransformIds ptransform_ids = new ResolveProdTransformIds( - ast_ids); - tree.apply(ptransform_ids); - - System.out.println("Verifying ast alternatives transform identifiers."); - ResolveTransformIds transform_ids = new ResolveTransformIds(ast_ids, - alt_ids, ptransform_ids); - tree.apply(transform_ids); - - System.out.println("Generating token classes."); - tree.apply(new GenTokens(ids)); - - System.out.println("Generating production classes."); - tree.apply(new GenProds(ast_ids)); - - System.out.println("Generating alternative classes."); - tree.apply(new GenAlts(ast_ids)); - - System.out.println("Generating analysis classes."); - tree.apply(new GenAnalyses(ast_ids)); - - System.out.println("Generating utility classes."); - tree.apply(new GenUtils(ast_ids)); - - try { - System.out.println("Generating the lexer."); - tree.apply(new GenLexer(ids)); - } catch (Exception e) { - System.out.println(e.getMessage()); - throw e; - } - - try { - System.out.println("Generating the parser."); - tree.apply(new GenParser(ids, alt_ids, transform_ids, ast_ids - .getFirstAstProduction(), processInlining, prettyPrinting, - hasTransformations)); - } catch (Exception e) { - System.out.println(e.getMessage()); - throw e; - } - } + private static boolean processInlining = true; + static int inliningMaxAlts = 20; + private static boolean prettyPrinting = false; + + private static final String OPT_LICENSE = "--license"; + private static final String OPT_D = "-d"; + private static final String OPT_NO_INLINE = "--no-inline"; + private static final String OPT_INLINE_MAX_ALTS = "--inline-max-alts"; + private static final String OPT_PRETTY_PRINT = "--pretty-print"; + + private static void displayCopyright() { + System.out.println(); + System.out.println("SableCC version " + Version.VERSION + + " HHU Version"); + System.out + .println("Copyright (C) 1997-2003 Etienne M. Gagnon <etienne.gagnon@uqam.ca> and"); + System.out.println("others. All rights reserved."); + System.out.println(); + System.out + .println("This software comes with ABSOLUTELY NO WARRANTY. This is free software,"); + System.out + .println("and you are welcome to redistribute it under certain conditions."); + System.out.println(); + System.out.println("Type 'sablecc -license' to view"); + System.out.println("the complete copyright notice and license."); + System.out.println(); + } + + private static void displayUsage() { + System.out.println("Usage:"); + System.out.println(" sablecc [" + OPT_D + " destination] [" + + OPT_NO_INLINE + "] [" + OPT_INLINE_MAX_ALTS + " number] [" + + OPT_PRETTY_PRINT + "] filename [filename]..."); + System.out.println(" sablecc " + OPT_LICENSE); + } + + public static void main(String[] arguments) { + String d_option = null; + Vector<String> filename = new Vector<>(); + + if (arguments.length == 0) { + displayCopyright(); + displayUsage(); + System.exit(1); + } + + if ((arguments.length == 1) && (arguments[0].equals(OPT_LICENSE))) { + new DisplayLicense(); + System.exit(0); + } + + displayCopyright(); + + { + int arg = 0; + while (arg < arguments.length) { + if (arguments[arg].equals(OPT_D)) { + if ((d_option == null) && (++arg < arguments.length)) { + d_option = arguments[arg]; + } else { + displayUsage(); + System.exit(1); + } + } else if (arguments[arg].equals(OPT_NO_INLINE)) { + processInlining = false; + } + /* + * A production is not inlined if it has more than + * inliningMaxAlts alternatives. The default value is 20. + */ + else if (arguments[arg].equals(OPT_INLINE_MAX_ALTS)) { + try { + inliningMaxAlts = Integer.parseInt(arguments[++arg]); + } catch (Exception e) { + displayUsage(); + System.exit(1); + } + } + /* + * if prettyprint flag is set to true, only the transformed + * grammar is printed on standard output + */ + else if (arguments[arg].equals(OPT_PRETTY_PRINT)) { + prettyPrinting = true; + } else { + filename.addElement(arguments[arg]); + } + arg++; + } + + if (filename.size() == 0) { + displayUsage(); + System.exit(1); + } + } + + try { + for (int i = 0; i < filename.size(); i++) { + processGrammar(filename.elementAt(i), d_option); + } + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + System.exit(0); + } + + /** + * The main method for processing grammar file and generating the + * parser/lexer. + * + * @param grammar + * input grammar file name + * @param destDir + * output directory name + */ + public static void processGrammar(String grammar, String destDir) + throws Exception { + File in; + File dir; + + in = new File(grammar); + in = new File(in.getAbsolutePath()); + + if (destDir == null) { + dir = new File(in.getParent()); + } else { + dir = new File(destDir); + dir = new File(dir.getAbsolutePath()); + } + + processGrammar(in, dir); + } + + /** + * The main method for processing grammar file and generating the + * parser/lexer. + * + * @param in + * input grammar file + * @param dir + * output directory + */ + public static void processGrammar(File in, File dir) throws Exception { + if (!in.exists()) { + System.out.println("ERROR: grammar file " + in.getName() + + " does not exist."); + System.exit(1); + } + if (!dir.exists()) { + System.out.println("ERROR: destination directory " + dir.getName() + + " does not exist."); + System.exit(1); + } + + // re-initialize all static structures in the engine + LR0Collection.reinit(); + Symbol.reinit(); + Production.reinit(); + Grammar.reinit(); + + System.out.println("\n -- Generating parser for " + in.getName() + + " in " + dir.getPath()); + + FileReader temp = new FileReader(in); + + // Build the AST + Start tree = new Parser(new Lexer(new PushbackReader( + temp = new FileReader(in), 1000))).parse(); + + temp.close(); + + boolean hasTransformations = false; + + if (((AGrammar) tree.getPGrammar()).getAst() == null) { + System.out + .println("Adding productions and alternative of section AST."); + // AddAstProductions astProductions = new AddAstProductions(); + tree.apply(new AddAstProductions()); + } else { + hasTransformations = true; + } + + System.out.println("Verifying identifiers."); + ResolveIds ids = new ResolveIds(dir); + tree.apply(ids); + + System.out.println("Verifying ast identifiers."); + ResolveAstIds ast_ids = new ResolveAstIds(ids); + tree.apply(ast_ids); + + System.out + .println("Adding empty productions and empty alternative transformation if necessary."); + tree.apply(new AddEventualEmptyTransformationToProductions(ids, ast_ids)); + + System.out + .println("Adding productions and alternative transformation if necessary."); + AddProdTransformAndAltTransform adds = new AddProdTransformAndAltTransform(); + tree.apply(adds); + /* + * System.out.println( + * "Replacing AST + operator by * and removing ? operator if necessary" + * ); tree.apply( new AstTransformations() ); + */ + System.out.println("computing alternative symbol table identifiers."); + ResolveAltIds alt_ids = new ResolveAltIds(ids); + tree.apply(alt_ids); + + System.out.println("Verifying production transform identifiers."); + ResolveProdTransformIds ptransform_ids = new ResolveProdTransformIds( + ast_ids); + tree.apply(ptransform_ids); + + System.out.println("Verifying ast alternatives transform identifiers."); + ResolveTransformIds transform_ids = new ResolveTransformIds(ast_ids, + alt_ids, ptransform_ids); + tree.apply(transform_ids); + + System.out.println("Generating token classes."); + tree.apply(new GenTokens(ids)); + + System.out.println("Generating production classes."); + tree.apply(new GenProds(ast_ids)); + + System.out.println("Generating alternative classes."); + tree.apply(new GenAlts(ast_ids)); + + System.out.println("Generating analysis classes."); + tree.apply(new GenAnalyses(ast_ids)); + + System.out.println("Generating utility classes."); + tree.apply(new GenUtils(ast_ids)); + + try { + System.out.println("Generating the lexer."); + tree.apply(new GenLexer(ids)); + } catch (Exception e) { + System.out.println(e.getMessage()); + throw e; + } + + try { + System.out.println("Generating the parser."); + tree.apply(new GenParser(ids, alt_ids, transform_ids, ast_ids + .getFirstAstProduction(), processInlining, prettyPrinting, + hasTransformations)); + } catch (Exception e) { + System.out.println(e.getMessage()); + throw e; + } + } }