001: /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
002: * This file is part of Beaver Parser Generator. *
003: * Copyright (C) 2003,2004 Alexander Demenchuk <alder@softanvil.com>. *
004: * All rights reserved. *
005: * See the file "LICENSE" for the terms and conditions for copying, *
006: * distribution and modification of Beaver. *
007: * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
008:
009: package beaver.comp.util;
010:
011: import java.io.PrintStream;
012:
013: import beaver.Scanner;
014: import beaver.Symbol;
015: import beaver.comp.io.SrcReader;
016:
017: /**
018: * Writes log in the following format:
019: * <pre>
020: * LogLevel:SL,SC-EL,EC: message
021: * </pre>
022: * Where SL, SC - line and column where issue start, EL,EC line and column where issue ends.
023: */
024: public class Log {
025: static public class Record {
026: static public class List {
027: private Record first, last;
028: private int size;
029:
030: public void add(Record rec) {
031: if (last == null)
032: first = last = rec;
033: else
034: last = last.next = rec;
035: size++;
036: }
037:
038: public Record start() {
039: return first;
040: }
041:
042: public int size() {
043: return size;
044: }
045:
046: public void reset() {
047: first = last = null;
048: size = 0;
049: }
050: }
051:
052: Record next;
053:
054: private final int start_pos;
055: private final int end_pos;
056: private final String message;
057:
058: Record(int start, int end, String msg) {
059: start_pos = start;
060: end_pos = end;
061: message = msg;
062: }
063:
064: public void report(String type, PrintStream out,
065: SrcReader src_reader) {
066: out.print(src_reader.file.getName());
067: out.print(':');
068: if (start_pos > 0) {
069: out.print(Symbol.getLine(start_pos));
070: out.print(',');
071: out.print(Symbol.getColumn(start_pos));
072: out.print('-');
073: out.print(Symbol.getLine(end_pos));
074: out.print(',');
075: out.print(Symbol.getColumn(end_pos));
076: out.print(':');
077: }
078: if (type != null) {
079: out.print(' ');
080: out.print(type);
081: out.print(':');
082: }
083: out.print(' ');
084: out.println(message);
085:
086: if (start_pos > 0) {
087: int start_line = Symbol.getLine(start_pos);
088: int end_line = Symbol.getLine(end_pos);
089: if (start_line == end_line) {
090: String line = src_reader.getLine(start_line)
091: .replace('\t', ' ');
092: out.print(line);
093: int start_column = Symbol.getColumn(start_pos);
094: int n;
095: for (n = start_column - 1; n > 0; n--) {
096: out.print(' ');
097: }
098: out.print('^');
099: for (n = Symbol.getColumn(end_pos) - start_column
100: - 1; n > 0; n--) {
101: out.print('-');
102: }
103: if (n == 0) {
104: out.print('^');
105: }
106: out.println();
107: }
108: }
109: }
110: }
111:
112: private Record.List errors = new Record.List();
113: private Record.List warnings = new Record.List();
114: private Record.List messages = new Record.List();
115:
116: public void error(Symbol symbol, String msg) {
117: error(symbol.getStart(), symbol.getEnd(), msg);
118: }
119:
120: public void error(Scanner.Exception e) {
121: int location = Symbol.makePosition(e.line, e.column);
122: error(location, location, e.getMessage());
123: }
124:
125: public void error(int start_pos, int end_pos, String msg) {
126: errors.add(new Record(start_pos, end_pos, msg));
127: }
128:
129: public void error(String msg) {
130: error(0, 0, msg);
131: }
132:
133: public void warning(Symbol symbol, String msg) {
134: warning(symbol.getStart(), symbol.getEnd(), msg);
135: }
136:
137: public void warning(int start_pos, int end_pos, String msg) {
138: warnings.add(new Record(start_pos, end_pos, msg));
139: }
140:
141: public void warning(String msg) {
142: warning(0, 0, msg);
143: }
144:
145: public void message(String msg) {
146: messages.add(new Record(0, 0, msg));
147: }
148:
149: public boolean hasErrors() {
150: return errors.size() > 0;
151: }
152:
153: public void report(String src_name, SrcReader src_reader) {
154: int n_err = errors.size(), n_warn = warnings.size();
155: if (n_err > 0 || n_warn > 0) {
156: PrintStream out = System.err;
157:
158: for (Record rec = errors.start(); rec != null; rec = rec.next) {
159: rec.report("Error", out, src_reader);
160: }
161: errors.reset();
162:
163: for (Record rec = warnings.start(); rec != null; rec = rec.next) {
164: rec.report("Warning", out, src_reader);
165: }
166: warnings.reset();
167:
168: if (n_err > 0 || n_warn > 0) {
169: out.print(src_name);
170: out.print(": ");
171: out.print(n_err);
172: out.print(" error");
173: if (n_err != 1)
174: out.print('s');
175: out.print(", ");
176: out.print(n_warn);
177: out.print(" warning");
178: if (n_warn != 1)
179: out.print('s');
180: out.println('.');
181: }
182: }
183: for (Record rec = messages.start(); rec != null; rec = rec.next) {
184: rec.report(null, System.out, src_reader);
185: }
186: messages.reset();
187: }
188: }
|