MyPL (My Playwright Language) Design Document
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)
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 valueState 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 valFILL "#email" WITH "a@b.c"Fill text field
READ "selector"SET text WITH READ ".header"Extract text from element
WAIT secondsWAIT 3Pause execution
LOG expressionLOG "Done" LOG counterPrint output
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")
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')