A recursive descent parser implementation in C for the Simple_PL1 programming language, built as part of CS 435 Compiler Construction coursework.
This project implements a complete lexical analyzer (scanner) and recursive descent parser for Simple_PL1, a simple imperative programming language. The parser validates source code syntax and reports errors with meaningful messages.
- Lexical Analysis: Tokenizes Simple_PL1 source code
- Syntax Analysis: Validates program structure using recursive descent parsing
- Error Reporting: Provides clear error messages for syntax and lexical errors
- Command-line Interface: Accepts source files as command-line arguments
| Token | Pattern | Examples |
|---|---|---|
| ID | (letter|_)(letter|digit|_)* |
max, a_1, _a1 |
| NUMBER | digit+ |
1, 21, 1024 |
| READ | read |
Reserved keyword |
| WRITE | write |
Reserved keyword |
| ASSIGN | := |
Assignment operator |
| PLUS | + |
Addition |
| MINUS | - |
Subtraction |
| TIMES | * |
Multiplication |
| DIV | / |
Division |
| SEMICOLON | ; |
Statement terminator |
| COMMA | , |
List separator |
| LPAREN | ( |
Left parenthesis |
| RPAREN | ) |
Right parenthesis |
program → stmt_list $
stmt_list → stmt stmt_list | ε
stmt → id := expr;
| read( id_list );
| write( expr_list );
expr → term ((+|-) term)*
term → factor ((*|/) factor)*
factor → ( expr ) | id | number
Valid Program:
x := 2;
y := 3;
read(a, b);
write(a, b, a+b*(2*x/y));
Output: Parsing complete. No errors.
- Visual Studio 2022
- C Compiler (MSVC)
- Windows OS (or compatible environment)
- Open the project in Visual Studio 2022
- Build the solution (Ctrl+Shift+B)
- The executable will be generated in the build directory
Run the parser from the command line with a source file:
name.exe source_file.txtparser.exe test1.txtThe parser detects and reports:
- Lexical Errors: Unrecognized characters
- Syntax Errors: Missing or unexpected tokens
Expected symbol: RPAREN
Expected symbol: SEMICOLON
Error in expression: Expected ID, NUMBER, or '('.
Unexpected symbol: DIV
.
├── scanner.c # Lexical analyzer implementation
├── scanner.h # Scanner header file
├── parser.c # Recursive descent parser
├── parser.h # Parser header file
├── main.c # Entry point
├── tokens.h # Token definitions
└── test_cases/ # Sample test files
├── valid/ # Valid programs
└── invalid/ # Programs with errors
scan()- Returns the next token from inputmatch(token)- Matches expected token or reports errorparse_program()- Entry point for parsingparse_stmt()- Parses statementsparse_expr()- Parses expressionsparse_term()- Parses termsparse_factor()- Parses factors
The parser uses predictive parsing with first sets to:
- Determine which production to apply
- Detect syntax errors early
- Provide meaningful error messages
Test files should cover:
- Valid programs with all language features
- Lexical errors (invalid characters)
- Syntax errors (missing/unexpected tokens)
- Edge cases (empty statements, nested expressions)
Located in test_cases/ directory:
test1.txt- Basic assignment and I/Otest2.txt- Complex expressionstest3.txt- Error cases