ANTLR4: Error message with complete offending source code line - antlr4

In case of an error I want to generate in my compiler an error message like e.g. clang, which contains the complete offending source code line.
Example:
1.c:3:7: error: use of undeclared identifier 'x'
if ( x== y) {
^
I have extended the ANTLR BaseErrorListener, but I have no idea
how to get the offending source code line (besides of the line number) as a string.

That's a simple thing. You get line number and char position in your error info. Use that to locate the position in your input. Then scan back and forward for line breaks. The text between those linebreaks is your source code line.

I created 2 methods in my extension of BaseErrorListener. One to get the source code line and another to get the '^' sign:
private String getSourceLine(String src, int line) {
String currentLine = "";
try (Scanner fileScanner = new Scanner(new File(src))) {
int currentLineNumber = 1;
while (fileScanner.hasNextLine()) {
currentLine = fileScanner.nextLine();
if (currentLineNumber == line) {
return currentLine + "\n";
}
currentLineNumber++;
}
} catch (Exception e) {
currentLine = "\n";
}
return currentLine;
}
private String getPointer(int charPosition) {
return StringUtils.repeat(' ', charPosition) + '^';
}
Calling them with:
String source = recognizer.getInputStream().getSourceName();
errorMessage += this.getSourceLine(source, line);
errorMessage += this.getPointer(charPositionInLine);

Related

Find word in textbox and get line number with this word C#

I have a problem, I have a text in texbox1 and I would like to search for a word there, and if I find it, I would like to get the line number from texbox1 where the found word is... is there such a possibility because I have already dug the whole internet and I can not find a solution :(
I try this:
private void button3_Click(object sender, EventArgs e)
{
int iL = 0;
foreach (string line in textBox1.Lines)
{
iL += 1;
if (line == "someword")
{
textBox2.Text = textBox1.Lines[iL].Remove(0, 15);
}
}
}
please help me because I am losing my mind :/
I just do it by my self ;) so thx for help...
And for others who want anwser..
string line = textBox1.Lines.FirstOrDefault(l => l.Contains("test"));
if (line != null)
{
textBox2.AppendText(line+Environment.NewLine); //all line with string test
textBox2.AppendText(line.Remove(0, 47) + Environment.NewLine);//only string test without 47 char from begining
}

stringstream peek() error C3867

I have method of a class, that accepts a key variable and looks up the key in an underdone map. The Value is a string example: "12132, jack_arog, 1990:12:8:3:25:3"; method will use peek() in stringstream to recognize ',' and ' ' to ignore them and put the rest in a vector. Afterwards method will assign members of vector to attributes of an object.
Error is recieve during compilation:
if (ss.peek() == ',' || ss.peek == ' ')
ss.ignore();
Error C3867 'std::basic_istream<char,std::char_traits<char>>::peek': non-standard syntax; use '&' to create a pointer to member
I looked up this error and most say you forgot () when calling a function, however i do not believe this is my problem.
Method:
void Account::find_account(std::string name, std::string ID)
{
std::string key = name + "," + ID;
Account new_account;
std::unordered_map<std::string, std::string>::const_iterator got = map.find(key);
if (got == map.end())
std::cout << "not found";
else
{
std::string my_string = got->second;
std::vector<std::string> holder;
std::stringstream ss(my_string);
std::string i;
while (!my_string.empty() && ss >> i)
{
holder.push_back(i);
if (ss.peek() == ',' || ss.peek == ' ')
ss.ignore();
}
for (int i = 0; i < holder.size(); i++)
{
if (i = 0)
new_account.ID = holder.at(i);
if (i = 1)
new_account.account_holder = holder.at(i);
if (i = 2)
{
std::string::size_type sz;
new_account.amount_available = std::stof(holder.at(i), &sz);
}
if (i = 3)
{
new_account.date_created = holder.at(i);
}
}
}
}
"I looked up this error and most say you forgot () when calling a function, however i do not believe this is my problem."
How can you say that when your compiler tells you that the error is exactly on this line? Moreover it is telling you that the error is specifically tied to your (ab)use of peek, I quote:
"...peek': non-standard syntax; use '&' to create a pointer to member
I translate: The compiler thinks you are not trying to call peek, since you did not type the required () to do so. So, if you are by any chance trying to get the function address, you should prepend & to the function name for the syntax to be correct.
Computers are dumb, I'll give you that, but they are rarely wrong.

Need help understand how Strings work in my method

I am trying to understand how this convertingStringToInt method works. I am reading a file, storing the values in an array and am to pass those values to the method to be converted. In the parameters of convertingStringToInt, I have (String number) I don't get where the String "number" is getting its values. So I am passing in a string called numbers, but how is that newly created String associated with any of the values in my file...?!?
I am trying to understand the cause all the return numbers are the error code -460 except the last digit in the file. So the String numbers is associated with the file somehow I just don't get how...
public static void read_file()
{
try {
File file = new File("randomNumbers.txt");
Scanner scan = new Scanner(file);
int amountOfNumbersInFile = convertingStringToInt(scan.nextLine()); // read the first line which is 100 to set array size
global_numbers = new int[amountOfNumbersInFile]; // set the array size equal to the first line read which is 100
for (int index = 0; index < amountOfNumbersInFile; index++)
{
String line = scan.nextLine();
global_numbers [index] = convertingStringToInt(line);
}
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static int convertingStringToInt(String numbers) //what does string "number" equal? why/where is it declared?
{
String numbers = scan.nextInt();
try {
return Integer.parseInt(numbers);
} catch (NumberFormatException n) {
return -460;
}
}
I have global_numbers declared as a global variable.
so the first thing u need understand is what u have in your txt file
if in this file you have only number is ok use stringToInt
but if you have words this never work properly

Getting Values out of a String with patterns

I have textfiles, which have attributes saved in Strings. Those Strings have a pattern like this:
[attributeName]:[value]
I can't generalize the [value], because it could be of any primitive datatype.
Saving the effectively values is not my concern, because it's depending on the user which attribute has to be loaded. The same file won't be loaded very often.
Now I have 2 problems:
1) For some reason the program which creates those files sometimes adds spaces around the : at some attributes and [value] could also contain spaces, so I have to get rid of those
2) Making the reading of those attributes more performant:
I've come up with this method:
public String getAttribute(File file, String attribute)
{
try
{
BufferedReader reader = new BufferedReader(new FileReader(file), 1024);
String line;
Pattern p = Pattern.compile(Pattern.quote(attribute), Pattern.CASE_INSENSITIVE);
while ((line = reader.readLine()) != null)
{
int i = line.indexOf(":");
if(line.charAt(i-1) == ' ')
line = line.substring(0,i-2) + line.substring(i);
if(line.charAt(i+1) == ' ')
line = line.substring(0,i) + line.substring(i+2);
if (p.matcher(line).find())
{
return line.replace(attribute, "").trim();
}
}
} catch (IOException e)
{
e.printStackTrace();
}
return null;
}
However, this method will probably be one of the most called by my application, so I can't leave it so unperformant as it is right now,
Thanks for any help!
I modified code to find appropriate line. Check example code below.
If you have a lot of files and attributes in these files you could think about saving somewhere pair attribute=value in code. In example code I provided very primitive cache by using Table interface from guava library.
Example code:
# guava library
import com.google.common.collect.Table;
import com.google.common.collect.HashBasedTable;
# apache commons lang
import static org.apache.commons.lang.StringUtils.startsWithIgnoreCase;
# apache commons io
import static org.apache.commons.io.IOUtils.closeQuietly;
[...]
# very primitive cache implementation. To find a value in table you have to
# pass row and column keys. In this implementation row is equal to file
# absolute path (because you can have 2 files with the same name) and column
# is equal to attribute name.
# If you have a lot of files and attributes probably you will have to clear
# from time to time the cache otherwise you will get out of memory
private static final Table<String, String, String> CACHE = HashBasedTable.create();
[...]
public String getAttribute(File file, String attribute) {
# get value for the given attribute from the given file
String value = CACHE.get(file.getAbsolutePath(), attribute);
# if cache does not contain value, method will read value from file
if (null == value) {
BufferedReader reader = null;
String value = null;
try {
reader = new BufferedReader(new FileReader(file), 1024);
String line;
while ((line = reader.readLine()) != null) {
# From your description I understood that each line in file
# starts with attribute name
if (startsWithIgnoreCase(line, attribute) {
# if we found correct line we simple split it by ':'
String[] array = line.split(":");
# this is to ensure that line contains attribute name
# and value
if (array.length >= 2) {
# we found value for attribute and we remove spaces
value = array[1].trim();
# we put value to the cache to speed up finding
# value for the same attribute in the future
CACHE.put(file.getAbsolutePath(), attribute, value);
break;
}
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
# you should always close
closeQuietly(reader);
}
}
return value;
}

Read special line from txt file in j2me

I have a text file, for example : file.txt, I want to read a line, for example line 7, have any way to read directly line 7 without reading other lines? I want to save memory from this work.
Because of the way JME been cut down you cannot do this. You would have to read whole file. Only other way, but may not be well suitable is to read the file , store it in RecordStore new entry per line, but is it really worth...
I think it is possible however you need to use a hashtable which might result to more heap usage.
Anyway, first, the contents of the text file should be stored in a char array. Then, second, the contents of the char array must be moved to the hashtable.
Each line in the text file is separated by a new line. In the char array, the new line (maybe) is translated to '\n'. Concatenate the characters in the array until the new line character is reached. The concatenated characters (minus '\n') will form the string in the first line. There should also be a counter here which should have been initialized to 0 (or 1, whatever you prefer). Save the text to the hashtable; The value will be the string that has been created and the key will be the counter. Increment the counter afterwards. Repeat this process for the remainder of the array until the end of file is reached.
With the hashtable, you can now get the string at line 7 without going through the other lines. Well, basically, each line has been read once. But, at least, you don't have to traverse each line once they have been stored in the hashtable.
Like what I have said earlier, doing this might increase heap usage especially if the text file is very large.
[And, by the way, sorry for the very late response. This is my first time here (I mean I just registered and answered this question) :D ]
Common Code
private String readLine(InputStream _inStream, int lineNum)
throws IOException {
if (null == _inStream) {
throw new IOException("Inputstream null.");
}
if (lineNum < 0) {
return ("Cannot read line a number " + lineNum);
}
final StringBuffer buf = new StringBuffer();
byte c;
int curLine = 1;
while (((c = (byte) _inStream.read()) != -1)) {
//System.out.println((char)c);
if (c == '\n') {
++curLine;
if (curLine > lineNum) {
break;
} else if (curLine < lineNum) {
continue;
}
} else if (curLine != lineNum) {
continue;
}
buf.append((char) c);
}
if (0 == buf.length()) {
return null;
} else {
return buf.toString().trim();
}
}
.
private String readLineWithSkip(InputStream _inStream, long skipCharacters)
throws IOException {
if (null == _inStream) {
throw new IOException("Inputstream null.");
}
if (skipCharacters < 1) {
return ("Cannot skip stream of " + skipCharacters + " characters");
}
final StringBuffer buf = new StringBuffer();
byte c;
_inStream.skip(skipCharacters);
while ((c = (byte) _inStream.read()) != '\n') {
//System.out.println((char)c);
buf.append((char) c);
}
if (0 == buf.length()) {
return null;
} else {
return buf.toString().trim();
}
}
.
InputStream inStream = null;
int fileLength = 39;
int skipCharacters = 10;
int lineNumber = 3;
String myLine = "No line read.";
try {
inStream = Class.class.getResourceAsStream("/test.txt");
if (null != inStream) {
inStream.mark(fileLength);
//For Approach II
myLine = readLine(inStream, lineNumber);
inStream.reset();
//For Approach I
myLine = readLineWithSkip(inStream, skipCharacters);
}
} catch (SecurityException se) {
se.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
try {
inStream.close();
} catch (IOException ex) {
ex.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}
inStream = null;
System.out.println(myLine);
}
.
Approach I: Map the line number with no of cumulative characters
Run the file through a code that maps the line number with the last of charater in that line from the 0th position of the file (to be used as skip() value) all +2 ('\r\n\') for each line. You can store this Mapping table either at the start or at the end of the same file.
The run the above common code with method readLineWithSkip(inStream,
skipCharacters); ONLY and judiciously commenting other method calls.
Points to Consider:
Skips to the desired position in the inputstream
Has an overhead of parsing the file and storing the mapping table.
.
Approach II: Read each line till the Nth line is read
The run the above common code with method readLine(inStream,
lineNumber); ONLY and judiciously commenting other method calls.
Points to Consider:
Slow since it has to read each character till it reaches the desired line
No overhead of parsing the file and no storing of the mapping table.
I would like to further simplify the problem of reading the chars without requiring any mapping of characters with line numbers.
...
Form form=new Form("filename");
InputStream fin=fconn.openDataInputStream();
StringBuffer buf =new StringBuffer();
int c;
int counter=-1;
while((c=fin.read())!=-1)
{
counter++;
if(counter==23)
{
form.append(buf.toString());
buf=null;counter=0;
continue;
}
buf.append((char)c);
}
if(counter<23 && counter>=0) // write the skipped chars between the last number read and the end of file
{
form.append(buf.toString());
buf=null;counter=0;
}
fin.close();
...
Hope this would help others.

Resources