An interactive Compiler Design lab project that converts an educational C-like source program into tokens and an Abstract Syntax Tree (AST). The extended workbench adds scoped semantic checks, scalar three-address code (TAC), quadruples, constant folding, control-flow/liveness analysis, register allocation and virtual target code. An independent Grammar Lab computes FIRST/FOLLOW, LL(1) tables and parsing traces. All stages use plain JavaScript.
Existing Render deployment: https://syntax-tree-visualizer-fwpv.onrender.com/
The extension is documented in EXTENSION_GUIDE.md, including the supported IR subset and a short demonstration sequence. The Render link above reflects whichever GitHub revision that deployment currently serves.
| Stage | Working feature |
|---|---|
| Semantic analysis | Undeclared and duplicate names, lexical scopes, constant writes, call arity, return and loop-control placement, basic string-to-numeric initializer check |
| Symbol table | Declaration kind, type annotation, scope and unique IR name |
| Intermediate code | Scalar expressions, function calls, conditionals and loops; TAC and quadruples |
| Optimization | Literal-only safe-integer constant folding with before/after instructions and rule log |
| Control flow | Basic blocks, labeled edges, separate function entries and structurally unreachable blocks |
| Grammar Lab | Editable grammar, FIRST/FOLLOW, LL(1) table, conflict/left-recursion detection and parsing trace |
| Data flow | Fixed-point live-variable sets and per-instruction next use |
| Code generation | 3/4/6-register virtual target with allocation/eviction trace and call barriers |
| Export | Analysis JSON with source, diagnostics, symbols, TAC, optimization and CFG |
These stages are visible in Compiler Workbench, below the existing AST workspace. Grammar Lab is a separate section with its own grammar and input. See SYLLABUS_MAPPING.md for the uploaded BCSE307L syllabus mapping and demo sequence. Editing the source clears previous analysis so exports cannot silently contain stale results.
Display syntax trees graphically with these required features:
- Zoom
- Tree traversal
- Node highlighting
- An interactive compiler teaching interface
- The user writes or pastes a program in the source-code editor.
- The tokenizer performs lexical analysis and creates a token stream.
- The recursive-descent parser checks the grammar and operator precedence.
- The parser constructs an Abstract Syntax Tree.
- The layout engine assigns a position to every AST node.
- The SVG renderer draws nodes and parent-child edges.
- The interface displays tokens, symbols, AST JSON, statistics, and traversals.
- Semantic analysis builds lexical scopes and diagnostics.
- Supported scalar programs produce TAC, optimized TAC and a control-flow graph.
flowchart TD
A[Source Code] --> B[Tokenizer and Parser]
B --> C[AST]
C --> D[Interactive SVG]
C --> E[Semantic Checks]
E --> F[Scalar TAC]
F --> G[Constant Folding]
F --> H[Control Flow]
Use this sequence during the lab evaluation:
- Open the live project.
- Select Advanced Program from the Example menu.
- Click Analyze Program.
- Point out the Nodes, Depth, Tokens, and Parser: Valid statistics.
- Click a tree node and explain its type, label, depth, and children.
- Open the Tokens tab to show lexical analysis.
- Open the Symbols tab to show functions, parameters, and variables.
- Open the AST JSON tab to show the internal tree representation.
- Select Preorder, Postorder, or Level-order and click Play or Step.
- Use +, −, drag-to-pan, Fit, and Reset to demonstrate tree navigation.
- Use Export SVG or download the AST JSON if required.
The Advanced Program demonstrates preprocessing input, recursion, typed functions, arrays, a for loop, nested if, continue, compound assignment, function calls, printf, and return.
Yes—the user can remove the example, type or paste a supported program, and click Analyze Program. Ctrl + Enter is the keyboard shortcut.
Example:
#include <stdio.h>
int factorial(int n) {
if (n <= 1) {
return 1;
}
return n * factorial(n - 1);
}
int main(void) {
int number = 5;
int answer = factorial(number);
printf("%d", answer);
return 0;
}The #include line is ignored because preprocessing occurs before syntax analysis in a real C compiler. The remaining source is tokenized, parsed, and visualized. This project creates the syntax tree; it does not execute the program or print its runtime result.
| Category | Supported examples |
|---|---|
| Variables | let x = 10;, const int limit = 5;, unsigned long total = 0; |
| Multiple declarations | int a = 1, b = 2, c; |
| Arrays | int values[3] = {1, 2, 3}; |
| Two-dimensional arrays | int matrix[2][2] = {{1, 2}, {3, 4}}; |
| Array indexing | values[i], matrix[row][column] |
| Pointers | int *ptr = &value;, *ptr = 9;, (*ptr)++; |
| Functions | function add(a, b) { ... }, int add(int a, int b) { ... } |
| Function calls | add(2, 3);, printf("%d", answer);, scanf("%d", &value); |
| Conditions | if, else, nested if, and else if |
| Loops | while, for, and do-while |
| Control flow | return, break, and continue |
| Assignments | =, +=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>= |
| Arithmetic | +, -, *, /, % |
| Comparison | <, <=, >, >=, ==, != |
| Logical | &&, ||, ! |
| Bitwise and shift | &, |, ^, ~, <<, >> |
| Updates | ++x, x++, --x, x-- |
| Conditional expression | condition ? first : second |
| Literals | Numbers, strings, characters, true, and false |
| Comments | // single-line and /* block */ |
| Preprocessor input | Lines beginning with #, such as #include, are safely ignored |
Normal statements must end with a semicolon. Braces, parentheses, and brackets must be balanced.
- Interactive SVG Abstract Syntax Tree
- Automatic large-tree fit with zoom levels down to 0.5%
- Zoom in, zoom out, mouse-wheel zoom, drag-to-pan, fit, and reset
- Clickable and keyboard-accessible nodes
- Selected-node properties and color highlighting
- Preorder, postorder, and level-order traversal
- Automatic traversal animation and manual step mode
- Token stream with line and column positions
- Basic symbol table for functions, parameters, and variables
- AST JSON view, copy, and download
- Complete-tree SVG export independent of the current zoom
- Friendly tokenizer and parser errors with exact locations
- Light and dark themes
- Responsive desktop, tablet, and mobile layout
- No framework, server, database, or external dependency
| Panel | Purpose |
|---|---|
| Visual Output | Displays the graphical AST and navigation controls |
| Node | Shows the selected node's ID, type, label, depth, and children |
| Tokens | Shows lexical tokens with line and column numbers |
| Symbols | Lists discovered functions, parameters, and variables |
| AST JSON | Shows and exports the exact JavaScript AST object |
| Grammar | Shows the main grammar and operator-precedence levels |
Open index.html in a modern browser.
Open a terminal in the project folder.
Windows:
py -m http.server 8000Linux or macOS:
python3 -m http.server 8000Then visit http://localhost:8000.
Node.js is only required for running the tests; it is not required to use the website.
node tests/parser-tests.js
node tests/compiler-tests.js
node tests/grammar-tests.js
node tests/backend-tests.jsThe suites contain 137 checks: 38 parser, 52 compiler, 26 grammar and 21 backend checks. The latter includes a test-only IR evaluator to verify loops, short-circuit evaluation, recursion, argument order, and matching original/optimized results. The website does not execute source programs. Parser checks cover:
- Valid expressions, declarations, functions, arrays, pointers, conditions, and loops
- A directly pasted C-style recursive factorial program
- Operator precedence and right-associative assignment AST structure
- Preprocessor-line handling and token source locations
- Clear rejection of invalid programs
- A 500-term stress expression
Expected final line:
ALL 38 TESTS PASSED
ALL 52 COMPILER TESTS PASSED
ALL 26 GRAMMAR TESTS PASSED
ALL 21 BACKEND TESTS PASSED
| File | Responsibility |
|---|---|
index.html |
Interface structure and compiler panels |
style.css |
Responsive layout, themes, nodes, and controls |
tokenizer.js |
Lexical analyzer and source-location tracking |
parser.js |
Recursive-descent parser and AST construction |
visualizer.js |
Tree layout, SVG rendering, zoom, pan, traversal, and export |
app.js |
UI events, examples, symbols, tokens, downloads, and statistics |
compiler.js |
Semantic analysis, TAC generation, constant folding and CFG construction |
backend.js |
Liveness, next use and local register-machine target generation |
grammar.js / grammar-ui.js |
Configurable grammar analysis and predictive parsing trace |
tests/grammar-tests.js / tests/backend-tests.js |
Grammar and target-code regression checks |
SYLLABUS_MAPPING.md |
BCSE307L implemented/missing topics and faculty demo |
compiler-ui.js |
Compiler stage panels, diagnostics, graph and analysis export |
tests/compiler-tests.js |
Compiler regression tests and test-only TAC evaluator |
EXTENSION_GUIDE.md |
Extension scope, architecture and demonstration |
tests/parser-tests.js |
Automated valid, invalid, structural, and stress tests |
PROJECT_REPORT.md |
Detailed academic project report |
VIVA_QUESTIONS.md |
Important viva questions with short answers |
program → statement* EOF
statement → declaration | function | expression ";"
| "print" "(" expression ")" ";"
| "if" "(" expression ")" statement ("else" statement)?
| "while" "(" expression ")" statement
| "for" "(" init ";" test ";" update ")" statement
| "do" statement "while" "(" expression ")" ";"
| "return" expression? ";" | "break" ";" | "continue" ";"
block → "{" statement* "}"
declaration → (let | var | const | type) declarator ("," declarator)* ";"
function → ("function" | type) ID "(" parameters? ")" block
expression → assignment | conditional
conditional → logical-or ("?" expression ":" conditional)?
unary → ("!" | "-" | "+" | "~" | "&" | "*" | "++" | "--") unary
| postfix
postfix → primary (call | index | "++" | "--")*
primary → literal | ID | array | "(" expression ")"
The parser separates logical, bitwise, equality, comparison, shift, addition, multiplication, unary, and postfix levels. Therefore, an expression such as 4 + 5 * 2 correctly places multiplication below addition in the AST.
| Operation | Method | Time complexity |
|---|---|---|
| Tokenization | Single left-to-right scan | O(n) source characters |
| Parsing | Recursive descent | Typically O(t) tokens |
| Tree construction | One wrapper per AST node | O(v) nodes |
| Tree layout | Postorder position assignment | O(v) nodes |
| Preorder/Postorder | Depth-first traversal | O(v) nodes |
| Level-order | Queue-based breadth-first traversal | O(v) nodes |
Invalid input does not leave an old tree on the screen. The visualizer clears the previous result, changes the parser status to Error, and shows a message with the line and column.
Example invalid input:
int value = 10Example response:
Expected ';' after variable declaration at line 1, column 15
This is a robust educational C-like parser, not a complete GCC, C++, or Java compiler. It intentionally focuses on lexical analysis, syntax analysis, AST construction, visualization, and traversal.
The following are outside the current scope:
- Program execution and runtime output
- Full macro expansion and preprocessing
- Structures, unions, classes, templates, and namespaces
switch/case,goto, and labels- Function prototypes without bodies
- Complete C/C++ declarator rules
- Complete C type checking, definite assignment and all-path return analysis
- Array/pointer memory lowering and native machine-code generation
Keeping the grammar focused makes every implemented compiler stage visible and explainable during a lab viva.
- Expand type compatibility and definite-assignment checks
- Add
switch/caseand structures - Extend TAC to arrays and pointer memory operations
- Highlight the source range belonging to a selected node
- Compare a concrete parse tree with the AST
- Add an interpreter for step-by-step execution