001 package org.hackystat.telemetry.analyzer.language.parser; 002 003 import java.io.BufferedReader; 004 import java.io.StringReader; 005 import java.util.ArrayList; 006 import java.util.List; 007 008 import org.hackystat.telemetry.analyzer.language.ast.TelemetryChartDefinition; 009 import org.hackystat.telemetry.analyzer.language.ast.TelemetryChartYAxisDefinition; 010 import org.hackystat.telemetry.analyzer.language.ast.TelemetryDefinition; 011 import org.hackystat.telemetry.analyzer.language.ast.TelemetryReportDefinition; 012 import org.hackystat.telemetry.analyzer.language.ast.TelemetryStreamsDefinition; 013 import org.hackystat.telemetry.analyzer.language.ast.TextPosition; 014 import org.hackystat.telemetry.analyzer.language.parser.impl.TelemetryLanguageParserImpl; 015 016 /** 017 * Parser for telemetry language. All static methods in this class are thread-safe. 018 * 019 * @author (Cedric) Qin Zhang 020 * @version $Id$ 021 */ 022 public class TelemetryLanguageParser { 023 024 /** 025 * Private construct to prevent this class from being instantiated. 026 * 027 */ 028 private TelemetryLanguageParser() { 029 } 030 031 /** 032 * Parsing full telemetry streams and charts definitions. 033 * 034 * @param string The definitions. 035 * @return A list containing <code>TelemetryDefinition</code> objects in the order appeared. 036 * 037 * @throws ParsingException If there is parsing error. 038 */ 039 @SuppressWarnings("unchecked") 040 public static List<TelemetryDefinition> parse(String string) throws ParsingException { 041 try { 042 TelemetryLanguageParserImpl parser 043 = new TelemetryLanguageParserImpl(new StringReader(string)); 044 List<TelemetryDefinition> defs = parser.all_input(); 045 TextExtractor textExtractor = new TextExtractor(string); 046 for (TelemetryDefinition def : defs) { 047 def.setDefinitionString(textExtractor.extract(def.getTextPosition())); 048 } 049 return defs; 050 } 051 catch (Throwable ex) { // might get JavaCC TokenMgrError 052 throw new ParsingException(ex); 053 } 054 } 055 056 /** 057 * Parses telemetry "streams" object definition. 058 * 059 * @param string A telemetry query statement that defines a telemetry "streams" object. 060 * Note that you should not include the final semi-colon. 061 * 062 * @return Java object representation of the "streams" definition. 063 * 064 * @throws ParsingException If the input is not grammatically correct. 065 */ 066 public static TelemetryStreamsDefinition parseStreamsDef(String string) throws ParsingException { 067 try { 068 TelemetryLanguageParserImpl parser 069 = new TelemetryLanguageParserImpl(new StringReader(string)); 070 TelemetryStreamsDefinition def = parser.streams_statement_input(); 071 def.setDefinitionString(new TextExtractor(string).extract(def.getTextPosition())); 072 return def; 073 } 074 catch (Throwable ex) { // might get JavaCC TokenMgrError 075 throw new ParsingException(ex); 076 } 077 } 078 079 /** 080 * Parses telemetry "chart" object definition. 081 * 082 * @param string A telemetry query statement that defines a telemetry "chart" object. 083 * Note that you should not include the final semi-colon. 084 * 085 * @return Java object representation of the "chart" definition. 086 * 087 * @throws ParsingException If the input is not gramatically correct. 088 */ 089 public static TelemetryChartDefinition parseChartDef(String string) throws ParsingException { 090 try { 091 TelemetryLanguageParserImpl parser 092 = new TelemetryLanguageParserImpl(new StringReader(string)); 093 TelemetryChartDefinition def = parser.chart_statement_input(); 094 def.setDefinitionString(new TextExtractor(string).extract(def.getTextPosition())); 095 return def; 096 } 097 catch (Throwable ex) { // might get JavaCC TokenMgrError 098 throw new ParsingException(ex); 099 } 100 } 101 102 /** 103 * Parses telemetry "chart y-axis" object definition. 104 * 105 * @param string A telemetry query statement that defines a telemetry "chart y-axis" object. 106 * Note that you should not include the final semi-colon. 107 * 108 * @return Java object representation of the "chart y-axis" definition. 109 * 110 * @throws ParsingException If the input is not gramatically correct. 111 */ 112 public static TelemetryChartYAxisDefinition parseChartYAxisDef(String string) 113 throws ParsingException { 114 try { 115 TelemetryLanguageParserImpl parser 116 = new TelemetryLanguageParserImpl(new StringReader(string)); 117 TelemetryChartYAxisDefinition def = parser.chart_y_axis_statement_input(); 118 def.setDefinitionString(new TextExtractor(string).extract(def.getTextPosition())); 119 return def; 120 } 121 catch (Throwable ex) { // might get JavaCC TokenMgrError 122 throw new ParsingException(ex); 123 } 124 } 125 126 /** 127 * Parses telemetry "report" object definition. 128 * 129 * @param string A telemetry query statement that defines a telemetry "report" object. 130 * Note that you should not include the final semi-colon. 131 * 132 * @return Java object representation of the "report" definition. 133 * 134 * @throws ParsingException If the input is not gramatically correct. 135 */ 136 public static TelemetryReportDefinition parseReportDef(String string) throws ParsingException { 137 try { 138 TelemetryLanguageParserImpl parser 139 = new TelemetryLanguageParserImpl(new StringReader(string)); 140 TelemetryReportDefinition def = parser.report_statement_input(); 141 def.setDefinitionString(new TextExtractor(string).extract(def.getTextPosition())); 142 return def; 143 } 144 catch (Throwable ex) { // might get JavaCC TokenMgrError 145 throw new ParsingException(ex); 146 } 147 } 148 149 /** 150 * Extracts text at given position. 151 * 152 * @author (Cedric) Qin ZHANG 153 * @version $Id$ 154 */ 155 private static class TextExtractor { 156 157 private List<String> lines = new ArrayList<String>(4); 158 159 /** 160 * Constructs this instance. 161 * 162 * @param input The input string. 163 * @throws Exception If the input string cannot be parsed into lines. 164 */ 165 private TextExtractor(String input) throws Exception { 166 BufferedReader reader = new BufferedReader(new StringReader(input)); 167 String line = reader.readLine(); 168 while (line != null) { 169 this.lines.add(line); 170 line = reader.readLine(); 171 } 172 reader.close(); 173 } 174 175 /** 176 * Extracts text at given position. 177 * 178 * @param textPosition The position. 179 * @return The extracted text. 180 * @throws Exception If we cannot extract the text. 181 */ 182 private String extract(TextPosition textPosition) throws Exception { 183 //Note: the index in textPosition is 1-indexed. 184 int startRow = textPosition.getBeginLine() - 1; 185 int startCol = textPosition.getBeginColumn() - 1; 186 int endRow = textPosition.getEndLine() - 1; 187 int endCol = textPosition.getEndColumn() - 1; 188 189 if (startRow < endRow) { 190 StringBuffer buffer = new StringBuffer(64); 191 String line = this.lines.get(startRow); 192 buffer.append(line.substring(startCol)).append('\n'); 193 for (int i = startRow + 1; i < endRow; i++) { 194 buffer.append(this.lines.get(i)).append('\n'); 195 } 196 line = this.lines.get(endRow); 197 buffer.append(line.substring(0, endCol + 1)); 198 return buffer.toString(); 199 } 200 else if (startRow == endRow) { 201 if (startCol <= endCol) { 202 String line = this.lines.get(startRow); 203 return line.substring(startCol, endCol + 1); 204 } 205 else { 206 throw new Exception("Begin column is greater than end column."); 207 } 208 } 209 else { 210 throw new Exception("Begin line is greater than end line."); 211 } 212 } 213 } 214 }