An error is a user-initiated action that results in a program's abnormal behavior or issues. It is critical to recovering these errors as quickly as possible because if they are not retrieved in a timely manner, they will lead to a situation from which it will be extremely difficult to recover.
All possible user errors are identified and reported to the user in the form of error messages during this phase of compilation. The Error Handling process is a way of locating errors and notifying them to users.
Error In Compiler Design
In general, a compiler error occurs whenever it fails to compile a line of code or an algorithm due to a bug in the code or a bug in the compiler itself. So, first, we'll look at various compiler mistakes, and then we'll talk about the recovery procedures that need to be used to fix the problems in a compiler.
The goals of the Error Handling process are to identify each error, display it to the user, and then develop and apply a recovery strategy to handle the error. The program's processing time should not be slow during this entire operation.
The blank entries in the symbol table are Errors. The parser should be able to discover and report program errors. The parser can handle any errors that occur and continue parsing the rest of the input. Although the parser is primarily responsible for error detection, faults can arise at any point during the compilation process.
Now we'll take a look at some common types of errors. There are three kinds of errors:
Compile-time errors
Runtime errors
Logical errors
Compile Time Errors
Compile-time errors appear during the compilation process before the program is executed. This can be due to a syntax error or a missing file reference that stops the application from compiling properly.
Types of Compile Time Errors
Now, we will have a look at the major three kinds of compile-time errors.
Lexical Phase errors
Syntactic phase errors
Semantic errors
Lexical Phase Errors
Misspellings of identifiers, keywords, or operators fall into this category. These errors occur both at the lexical phase and during program execution. When a series of characters does not satisfy the pattern of any token, a lexical error occurs. These mistakes might occur as a result of spelling mistakes or the appearance of any unlawful characters.
In general, lexical errors occurs when:
Identifier or numeric constants are too long.
Characters that seem to be illegal.
Strings that don't match.
Example:
class Factorial{
public static void main(String args[]){
int i,fact=1;
int number=5;
for(i=1;i<=number;i++){
fact=fact*i;
}
System.out.println("Factorial of "+number+" is: "+fact);$$$
}
}
Here, we have used a non-readable syntax after the print statement which results in an error and it comes under lexical error. So, the error will look like:
error: illegal start of expression
Syntactic Phase Errors
These problems arise during the syntactic phase and execution. These issues occur when there is an imbalance in the parenthesis or when some operators are missing. For example, a semicolon that isn't there or a parenthesis that isn't balanced.
Typically Syntactic errors look like this:
Discrepancies in the structure
The operator is absent.
Misspelled Keywords
Parenthesis that aren't balanced
Example:
class Factorial{
public static void main(String args[]){
int i,fact=1;
int number == 5;
for(i=1;i<=number;i++){
fact=fact*i;
}
System.out.println("Factorial of "+number+" is: "+fact);
}
}
The above code has a syntactic error since we need to use =(assigment operator) in the statement, but we're using invalid expression (==) instead.
Semantic Errors
These errors are detected during the compilation time of a program when they occur during the semantic analysis step. These problems occur when operators, variables, or undeclared variables are used incorrectly. Like the type conflicts between operator and operand or incompatible value assignment.
Some of the semantic errors are
Inappropriate types of operands
Variables that were not declared
Actual arguments do not match a formal argument.
Example:
class Factorial{
public static void main(String args[]){
int i;
int number = 5;
for(i=1;i<=number;i++){
fact=fact*i;
}
System.out.println("Factorial of "+number+" is: "+fact);
}
}
The above code will produce an error as we didn’t declare the variable “fact” which generates a semantic error. And hence the output looks like:
error: cannot find symbol
Runtime Errors
A run-time error occurs during the execution of a program and is most commonly caused by incorrect system parameters or improper input data. This can include a lack of memory to run an application, a memory conflict with another software, or a logical error, which is an example of run-time error.
These are errors that occur when a user enters improper syntax into a code or enters code that a typical compiler cannot run.
Logical Errors
When programs execute poorly and yet don't terminate abnormally, logic errors occur. A logic error can result in unexpected or unwanted outputs or other behavior, even if it is not immediately identified as such. These are errors that occur when the specified code is unreachable or when an infinite loop is present.
Now, We'll look at several error recovery mechanisms in a compiler as we've got a good knowledge of the different types of errors.
Modes of Error Recovery
The compiler's simplest requirement is to simply stop, issue a message, and halt compiling. To cope with problems in the code, the parser can implement one of five typical error-recovery mechanisms in the following which are some of the most prevalent recovery strategies.
Panic Mode Recovery
This method involves removing successive characters from the input one by one until a set of synchronized tokens are found. Delimiters, such as a semicolon, opening, or closing parenthesis, for example, are synchronizing tokens.
For example,
int a, $b, sum, 5z;
Since variable declaration starts with invalid symbols ($) and numbers (5) hence Panic mode recovery will discard such variables until it synchronized tokens such as commas or semicolons are not found.
The benefit is that it's simple to implement and ensures that you won't get stuck in an infinite loop. The drawback is that a significant amount of data is skipped without being checked for additional problems.
Statement Mode Recovery
When a parser detects an error, it attempts to rectify the problem so that the rest of the statement's inputs allow the parser to continue parsing. Inserting a missing semicolon, replacing a comma with a semicolon, and so forth. Designers of parsers must exercise caution here, as one incorrect correction could result in an unending cycle.
One drawback is that it is difficult to deal with circumstances where the real problem occurred prior to the detection moment.
Error Productions
If a compiler designer is aware of prevalent errors, these types of faults can be recovered by enhancing the grammar with error production that results in improper constructs. Maintaining it is extremely difficult and problematic.
Error productions are used to recover syntactic phase errors.
Global Corrections
The parser looks over the entire program and tries to figure out what it's supposed to accomplish, then finds the closest match that's error-free.
When given an incorrect input (statement) X, it generates a parse tree for the closest error-free statement Y. This method may allow the parser to make minimum changes to the source code, but it has yet to be deployed in practice due to its complexity (time and space).
Using Symbol Table
In semantic errors, the errors are retrieved by using a symbol table for the relevant identifier, and the compiler does automated type conversion if the data types of two operands are incompatible.
Example:
int data1 = “10”;
String data2 = "12";
int data3 = data1 + data2;
So, after compiling this statement, it will result in the following parse tree:
data1 should be fixed by turning it into a string and then appending the two strings together. Although there is an error in this statement, the compiler makes assumptions and resolves them.
The diagram given below depicts in which phases the recovery methods can be applied.
Frequently Asked Questions(FAQs)
What type of errors are recovered by Panic Mode Recovery?
What is the difference between Compile-time and Runtime?
Compile-time refers to the time it takes to transform programming code to machine code (i.e. binary code). The runtime of a program is the time it spends running after it has been compiled.
What is a Single bit error?
A single-bit error is a single bit of a data unit that is altered from 0 to 1 or from 1 to 0.
What is the role of the Error Handler in error handling techniques?
The Error Handling process's tasks are to detect each error, report it to the user, and then devise and implement a recovery strategy to handle the error.
How to find or report an error?
The viable-prefix feature of a parser allows the compiler for early detection of syntax errors.
What will happen if the length of any variable exceeds the limit?
The compiler will detect and throw a Long identifier error during the lexical phase analysis of the compilation process.
Conclusion
To summarize the article, we talked about the various types of errors and the famous concept of error handling. After that, we learned the error recovery methods used in various phases of compiling. And we also discussed the most asked doubts. Hope you learned something.