python interpreter.py ./path/to/file
- English-like syntax for web automation
- Minimalist, space-separated commands
- Case-sensitive with specific conventions:
- Keywords: ALL CAPS (e.g.,
OPEN
,SET
) - Variables: lowercase (e.g.,
counter
,username
) - Comments: Start with # (e.g.,
# This is a comment
)
- Keywords: ALL CAPS (e.g.,
- Integers (e.g.,
3
,42
) - Strings (double-quoted, e.g.,
"hello"
) - Implicit Booleans (evaluated during runtime)
- Browser navigation
- Element interaction (clicks, fills)
- Text extraction
- Automatic waiting
- Manual waiting
- Variables and assignments
- Conditionals and loops
- Error handling
Keyword | Purpose |
---|---|
OPEN | Navigate to URL |
WAIT | Pause execution |
CLICK | Click element |
FILL | Fill form field |
READ | Extract text from element |
LOG | Print output |
SET | Variable assignment |
IF | Conditional block |
ELSE | Alternative block |
WHILE | Loop construct |
TRY | Error handling block |
CATCH | Error recovery block |
HAS | String contains operator |
IS | Equality operator |
< | Less-than operator |
> | Greater-than operator |
<= | Less-than-equals operator |
Component | Examples | Purpose |
---|---|---|
Navigation | OPEN "url" | Page control |
Element Actions | CLICK "#btn" | UI interaction |
Data Flow | SET var WITH value | State management |
Control Logic | IF (cond) { ... } | Conditional execution |
Error Handling | TRY { ... } CATCH { ... } | Resilient execution |
- Space-separated tokens
- Number of spaces between commands doesn’t matter
- No newlines required (but supported for readability)
- Example:
OPEN "url"
WAIT 3
CLICK "#btn"
Command | Example | Description |
---|---|---|
OPEN "url" | OPEN "https://example.com" | Navigate to URL |
CLICK "selector" | CLICK "#submit-btn" | Click element |
FILL sel WITH val | FILL "#email" WITH "a@b.c" | Fill text field |
READ "selector" | SET text WITH READ ".header" | Extract text from element |
WAIT seconds | WAIT 3 | Pause execution |
LOG expression | LOG "Done" LOG counter | Print output |
SET variable WITH value
- Examples:
SET name WITH "Maaz" # String assignment SET count WITH 5 # Integer assignment SET copy WITH original # Variable copying
- Referenced by name (lowercase)
- Example:
LOG count
FILL "#name" WITH username
Operator | Description | Example |
---|---|---|
IS | Equality | (var IS 5), (var IS “text”) |
HAS | String contains | (var HAS “substr”) |
< | Less than | (var < 10) |
> | Greater than | (var > 10) |
<= | Less than equals | (var <= 10) |
IF (condition) {
# commands
} ELSE {
# commands
}
SET status WITH READ "#status"
IF (status HAS "success") {
CLICK "#next"
} ELSE {
LOG "Operation failed"
}
WHILE condition {
# commands
}
SET counter WITH 0
WHILE counter < 5 {
LOG counter
SET counter WITH counter + 1
}
TRY {
# commands
} CATCH {
# error handling
}
TRY {
CLICK "#unstable-element"
} CATCH {
LOG "Element not found"
CLICK "#fallback-btn"
}
OPEN "https://example.com/login"
SET username WITH READ "#username-label"
IF (username HAS "Admin") {
FILL "#user" WITH "admin@test.com"
} ELSE {
FILL "#user" WITH "guest@test.com"
}
TRY {
CLICK "#login-btn"
} CATCH {
LOG "Login button missing!"
}
ON ".welcome"{
SET welcome_text WITH READ ".welcome"
IF (welcome_text HAS "Admin") {
FILL "#auth" WITH "admin-pass"
} ELSE {
FILL "#auth" WITH "default-pass"
}
TRY {
CLICK "#submit"
WAIT 2 # Wait for navigation
LOG "Login success!"
} CATCH {
LOG "Failed: element not found"
}
}
- Playwright errors (timeouts, missing elements)
- MyPL runtime errors (undefined variables)
- Syntax errors
- Unsupported commands
- Lexer: Tokenizes input (e.g.,
OPEN
→TokenType.NAVIGATE
) - Parser: Builds Abstract Syntax Tree (AST) from tokens
- Interpreter: Executes AST using Playwright and Python
interface Program {
type: "Program";
body: Node[];
}
interface NavigateExpression {
type: "NavigateExpression";
url: Literal;
}
interface AssignmentExpression {
type: "AssignmentExpression";
target: Identifier;
value: Expression;
}
interface TryCatchExpression {
type: "TryCatchExpression";
try: Statement[];
catch: Statement[];
}
- Lexical Analysis: Tokenizes source code using regex patterns
- Example:
"CLICK"
→(CLICK, "CLICK")
- Example:
- Parsing: Builds AST and validates syntax
- Execution: Walks AST and performs actions using Playwright
Component | Responsibility |
---|---|
Lexer | Transforms source code into token pairs |
Parser | Constructs and validates the Abstract Syntax Tree (AST) |
Runtime | Manages state and executes the AST |
Playwright Adapter | Handles browser interactions using Playwright |
token_spec = [
("FILL", r'\bFILL\b'),
("TRY", r'\bTRY\b'),
("CATCH", r'\bCATCH\b'),
("ON", r'\bON\b'),
("WAIT", r'\bWAIT\b'),
("OPEN", r'\bOPEN\b'),
("READ", r'\bREAD\b'),
("WITH", r'\bWITH\b'),
("SET", r'\bSET\b'),
("LOG", r'\bLOG\b'),
("CLICK", r'\bCLICK\b'),
("WHILE", r'\bWHILE\b'),
("IF", r'IF'),
("ELSE", r'ELSE'),
("INTEGER_LITERAL", r'\b\d+\b'),
("STRING_LITERAL", r'"([^"]*)"'),
("LOGICAL_OPERATOR", r'==|\bHAS\b|\bIS\b|[<>]=?'),
("ARITHMETIC_OPERATOR", r'\+|\-|\*|\/'),
("IDENTIFIER", r'\b[a-z][a-zA-Z0-9_]*\b'),
("L_BRACE", r'\{'),
("R_BRACE", r'\}'),
("L_PAREN", r'\('),
("R_PAREN", r'\)'),
]
- Input: Source code file
- Processing:
- Scan stream using regex patterns
- Filter out whitespace/comments
- Generate token stream
- Output: Sequence of (token_type, value) pairs
- Recursive Descent: Each grammar rule has a corresponding method
- Validation: Strict token expectations
- AST Generation: Structured program representation in JSON
Method | Responsibility |
---|---|
parse_statement() | Top-level dispatch |
parse_expression() | Handle values and operators |
parse_block() | Process { … } groups |
parse_conditional() | Handle IF/ELSE logic |
{
"type": "ConditionalExpression",
"conditional": {
"type": "BinaryExpression",
"operator": "HAS",
"left": {"type": "Identifier", "name": "status"},
"right": {"type": "Literal", "value": "success"}
},
"then": [...],
"else": [...]
}
- Initialize Playwright browser
- Store variables in a dictionary
- Traverse AST:
- Resolve variables
- Execute Playwright commands
- Handle errors
- Automatic waiting for elements
- Direct mapping to browser actions:
CLICK
→page.locator().click()
FILL
→page.locator().fill()
READ
→page.locator().text_content()
ON
→page.locator().wait_for(state ='visible')