-
Notifications
You must be signed in to change notification settings - Fork 0
Home
Try it online: khalidalkhaldi.pythonanywhere.com
- What is Kencode?
- Why Kencode?
- How It Works
- Installation
- Usage
- Kencode Classification (Four Token Types)
- Base-Word Reference Table
- Operator Reference Table
- Escape Sequence Reference
- The Kencode Sequence & General Rule
- Reading a Kencode Instruction
- Complete Examples by Category
- For Technical Users
- Token classification rules
- Advantages of Kencode
- Citation and Reference
- License
Kencode is a bidirectional mapping method between Python programming code and natural spoken or written language instructions. It was designed to make programming accessible to people who face difficulties with the punctuation and special characters that conventional programming requires, such as people using voice input, alternative keyboards, or those learning to code for the first time.
With Kencode, instead of typing:
student = 'James'You write or speak:
student equals string James
And instead of:
for i in range(5):You write or speak:
for variable i in call range pass digit five
Kencode is fully bidirectional: you can convert Python → Kencode, or Kencode → Python.
Programming languages rely heavily on punctuation, (), [], {}, ', ", #, :, =, +=, and special characters that are difficult for many people to type or dictate. This creates a significant barrier:
- People using voice-to-text input struggle with special characters
- People with motor disabilities find special-character keyboard shortcuts difficult
- Beginner programmers often confuse punctuation rules and syntax symbols
- People using alternative input devices may not have easy access to symbol keys
- Non-native speakers learning programming face both language and syntax barriers simultaneously
Kencode solves this by providing a clean, word-based alternative that maps one-to-one with real Python code. No information is lost, and any valid Kencode instruction can be converted back to exactly the Python it represents.
Kencode works by breaking every Python statement into a sequence of classified tokens. Each token falls into one of four categories, and the sequence of categories is called the Kencode Sequence (KS). Alongside the KS, each token also has a verbal form, a plain English word or phrase, which together form the Kencode Verbal Instruction (KVI).
Python: x = 10
KS: [W] [O] [B] [W]
KVI: x equals digit ten
The KS tells you what kind of thing each token is. The KVI tells you what it says. Together, they give a complete, unambiguous description of the Python code in natural language.
pip install KencodeRequires Python 3.9 or higher. No external dependencies.
from kencode import python_to_kencode, decode_kvi
# Python → Kencode
ks, kvi = python_to_kencode("x = 10")
print(ks) # [W][O][B][W]
print(kvi) # x equals digit ten
# Kencode → Python
ks, py = decode_kvi("x equals digit ten")
print(py) # x = 10from kencode import python_to_kencode
with open("my_script.py", "r") as f:
lines = f.readlines()
for i, line in enumerate(lines, 1):
ks, kvi = python_to_kencode(line.rstrip())
if ks:
print(f"Line {i:>3}: {line.rstrip()}")
print(f" KS : {ks}")
print(f" KVI: {kvi}")
print()from kencode import python_to_kencode
import csv
input_file = "my_script.py"
output_file = "my_script_kencode.csv"
with open(input_file, "r") as f:
lines = f.readlines()
with open(output_file, "w", newline="") as f:
writer = csv.writer(f)
writer.writerow(["line_no", "python_code", "KS", "KVI"])
for i, line in enumerate(lines, 1):
ks, kvi = python_to_kencode(line.rstrip())
writer.writerow([i, line.rstrip(), ks, kvi])
print(f"Saved to {output_file}")from kencode import decode_kvi
with open("my_instructions.txt", "r") as f:
lines = f.readlines()
for i, line in enumerate(lines, 1):
line = line.strip()
if line:
ks, py = decode_kvi(line)
print(f"Line {i:>3}: {line}")
print(f" KS : {ks}")
print(f" PY : {py}")
print()from kencode import python_to_kencode, decode_kvi
original = "for i in range(5):"
ks, kvi = python_to_kencode(original)
ks2, py = decode_kvi(kvi)
print(f"KS : {ks}") # [K][B][W][K][B][W][B][B][W]
print(f"KVI : {kvi}") # for variable i in call range pass digit five
print(f"PY : {py}") # for i in range(5):from kencode.kencode_converter import process_file
process_file("my_script.py")
# Prints KS + KVI for every line to terminal
# Saves my_script_kencode.csv automaticallyKencode installs two CLI commands: kencode for encoding and kencode-decode for decoding.
kencode my_script.pyPrints KS and KVI for every line to the terminal and saves my_script_kencode.csv automatically.
kencode-decode "x equals digit ten"Output:
KS : [W][O][B][W]
PY : x = 10
kencode-decode -f my_instructions.txtEach line in the file is decoded and printed with its KS and Python code.
kencode-decodeKencode KVI -> Python (type 'quit' to exit)
KVI> name equals string Alice
KS : [W][O][B][W]
PY : name = "Alice"
KVI> for variable i in call range pass digit five
KS : [K][B][W][K][B][W][B][B][W]
PY : for i in range(5):
KVI> quit
| Task | Method | Command / Code |
|---|---|---|
| Encode one line | Library | python_to_kencode("x = 10") |
| Decode one KVI | Library | decode_kvi("x equals digit ten") |
| Encode a file | Library | process_file("script.py") |
| Encode a file | CLI | kencode script.py |
| Decode one KVI | CLI | kencode-decode "x equals digit ten" |
| Decode a file | CLI | kencode-decode -f instructions.txt |
| Interactive mode | CLI | kencode-decode |
Every token in a programming statement is classified by Kencode into four types:
| Symbol | Name | Meaning | Examples |
|---|---|---|---|
[K] |
Keyword | A Python reserved word that controls program flow or structure |
if, for, while, def, class, return, True, False, print
|
[O] |
Operator | A mathematical, logical, or assignment operation |
=, +, -, *, /, ==, >=, and, or
|
[W] |
Word | A user-defined name, variable, number verbal, or string content |
student, ten, Alice, my, list
|
[B] |
Base-word | A Kencode structural word that classifies or bridges tokens |
variable, digit, string, call, pass, list, key, value
|
-
[K]tokens come from Python's built-in reserved words. They appear in the KVI exactly as they are in Python (lowercased). -
[O]tokens are translated to their verbal equivalents:==becomesis equal,>=becomesgreater or equal,**becomespower. -
[W]tokens are plain words, variable names (split on underscores), string content, or verbalized numbers. -
[B]tokens are the glue of Kencode. They are added to indicate the type of value or structure that follows.
Note: Programming statements provide
[K],[O], and[W]. We need to add only[B]to construct a valid Kencode instruction.
| Base-Word | KS Tag | Associated Type | Description |
|---|---|---|---|
variable |
[B] |
Data / names | A named reference to a stored value |
digit |
[B] |
Numbers | A numeric literal (integer or float) |
point |
[B] |
Numbers | The decimal point in a float (3.5 → digit three point 5) |
string |
[B] |
Text | An immutable sequence of characters |
special |
[B] |
Escape sequences | Introduces an escape character within a string |
list |
[B] |
Collections | An ordered, mutable collection [...]
|
tuple |
[B] |
Collections | An ordered, immutable collection (...)
|
set |
[B] |
Collections | An unordered, unique-value collection {...}
|
dict |
[B] |
Collections | A dictionary comprehension marker |
key |
[B] |
Dictionaries | The key in a key-value pair or subscript ["key"]
|
value |
[B] |
Dictionaries | The value in a key-value pair |
index |
[B] |
Lists / strings | A positional subscript [0], [-1]
|
call |
[B] |
Functions | Marks the start of a function call |
pass |
[B] |
Functions | Marks the start of arguments passed to a call |
object |
[B] |
OOP | An object being accessed via dot notation |
attribute |
[B] |
OOP | A property accessed with a dot (non-callable) |
method |
[B] |
OOP | A callable property accessed with a dot |
hook |
[B] |
OOP | A dunder method like __init__
|
tab |
[B] |
Structure | Represents one indentation level (preceded by a count [W]) |
comment |
[B] |
Structure | Marks a comment line (replaces #) |
f-string |
[B] |
Formatting | An f-string literal f"..."
|
formatting |
[B] |
Formatting | A {...} expression inside an f-string |
precision |
[B] |
Formatting | A .Nf format specifier |
left-align |
[B] |
Formatting | The :<N alignment specifier |
right-align |
[B] |
Formatting | The :>N alignment specifier |
center-align |
[B] |
Formatting | The :^N alignment specifier |
expression |
[B] |
Lambda | Marks the body of a lambda expression |
type |
[B] |
Exceptions | Introduces an exception class name |
ignore |
[B] |
Placeholder | Represents _ (the throwaway variable) |
keyword-only |
[B] |
Functions | The * separator in function parameters |
dictionary |
[B] |
Functions | A **kwargs-style parameter or argument |
list unpack |
[B][B] |
Functions | A *args unpacking in a function call |
dictionary unpack |
[B][B] |
Functions | A **kwargs unpacking in a function call |
| Python Symbol | KVI Verbal | Category |
|---|---|---|
= |
equals |
Assignment |
+= |
plus equal |
Compound assignment |
-= |
minus equal |
Compound assignment |
*= |
times equal |
Compound assignment |
/= |
divided equal |
Compound assignment |
%= |
modulo equal |
Compound assignment |
**= |
power equal |
Compound assignment |
//= |
floor divided equal |
Compound assignment |
+ |
plus |
Arithmetic |
- |
minus |
Arithmetic |
* |
times |
Arithmetic |
/ |
divided by |
Arithmetic |
// |
floor divided by |
Arithmetic |
% |
modulo |
Arithmetic |
** |
power |
Arithmetic |
== |
is equal |
Comparison |
!= |
not equal |
Comparison |
< |
less than |
Comparison |
> |
greater than |
Comparison |
<= |
less or equal |
Comparison |
>= |
greater or equal |
Comparison |
in |
in |
Membership |
not |
not |
Logical |
and |
and |
Logical |
or |
or |
Logical |
is |
is |
Identity |
| Escape | KVI Verbal | Meaning |
|---|---|---|
\n |
new line |
Newline character |
\t |
horizontal tab |
Horizontal tab |
\\ |
backslash |
Literal backslash |
\' |
single quote |
Literal single quote |
\" |
double quote |
Literal double quote |
\r |
carriage return |
Carriage return |
\b |
backspace |
Backspace |
\f |
form feed |
Form feed |
\a |
bell |
Bell / alert |
\v |
vertical tab |
Vertical tab |
\ooo |
octal ooo |
Octal value |
\xhh |
hex hh |
Hexadecimal value |
\uXXXX |
unicode XXXX |
Unicode code point |
lines = ["line one\n", "line two\n"]KS: [W][O][B][B][W][W][B][W][W][B][W][W][B][W][W]
KVI: lines equals list string line one special new line string line two special new line
The Kencode Sequence (KS) captures the structural pattern of a Python statement using only the four token symbols. This is the single general regex rule that validates any KS:
^(?:\d+\s+)?(\[(?:K|O|W|B)\])+$
| Part | Meaning |
|---|---|
^ |
Start of the sequence |
(?:\d+\s+)? |
Optional indent prefix, a digit followed by a space (e.g. 1 for one indent level) |
(\[(?:K|O|W|B)\])+ |
One or more tags, each exactly [K], [O], [W], or [B]
|
$ |
End of the sequence |
A Kencode instruction reads left to right. Base-words [B] act as type classifiers, they always appear immediately before the token they describe:
[W]my [W]list [O]equals [B]list [B]digit [W]one [B]digit [W]two [B]digit [W]three
Corresponds to:
my_list = [1, 2, 3]| Pattern | Meaning | Python example |
|---|---|---|
[W][O][B][W] |
Simple assignment | x = 10 |
[W][O][B][W][B][W] |
Float assignment | y = 3.5 |
[K][B][W][K][B][W][B][B][W] |
For loop with call | for i in range(5): |
[B][W][B][B][args...] |
Function call | greet("Alice") |
[W][B][W] |
Method call (no args) | my_list.sort() |
[W][B][W][B][B][W] |
Method call (with args) | my_list.append(4) |
[W][B][K][B][W][B][B][W][B][W] |
__init__ with indent |
def __init__(self, name): |
| Python | KS | KVI |
|---|---|---|
x = 10 |
[W][O][B][W] |
x equals digit ten |
y = 3.5 |
[W][O][B][W][B][W] |
y equals digit three point 5 |
name = "Alice" |
[W][O][B][W] |
name equals string Alice |
is_valid = True |
[W][W][O][K] |
is valid equals true |
my_list = [1, 2, 3] |
[W][W][O][B][B][W][B][W][B][W] |
my list equals list digit one digit two digit three |
my_tuple = (1, 2, 3) |
[W][W][O][B][B][W][B][W][B][W] |
my tuple equals tuple digit one digit two digit three |
my_set = {1, 2, 3} |
[W][W][O][B][B][W][B][W][B][W] |
my set equals set digit one digit two digit three |
| Python | KS | KVI |
|---|---|---|
print(x + y) |
[K][B][W][O][B][W] |
print variable x plus variable y |
print(a ** b) |
[K][B][W][O][B][W] |
print variable a power variable b |
x += 5 |
[W][O][B][W] |
x plus equal digit five |
result = "Pass" if score >= 50 else "Fail" |
[W][O][B][W][K][B][W][O][B][W][K][B][W] |
result equals string Pass if variable score greater or equal digit fifty else string Fail |
| Python | KS | KVI |
|---|---|---|
if result: |
[K][B][W] |
if variable result |
if True: |
[K][K] |
if true |
if num == 0: |
[K][B][W][O][B][W] |
if variable num is equal digit zero |
elif num > 0: |
[K][B][W][O][B][W] |
elif variable num greater than digit zero |
else: |
[K] |
else |
while count < 5: |
[K][B][W][O][B][W] |
while variable count less than digit five |
for i in range(5): |
[K][B][W][K][B][W][B][B][W] |
for variable i in call range pass digit five |
for i in range(1, 10, 2): |
[K][B][W][K][B][W][B][B][W][B][W][B][W] |
for variable i in call range pass digit one digit ten digit two |
for _ in range(3): |
[K][B][K][B][W][B][B][W] |
for ignore in call range pass digit three |
for key, value in my_dict.items(): |
[K][B][W][B][W][K][B][W][W][B][W] |
for variable key variable value in variable my dict method items |
| Python | KS | KVI |
|---|---|---|
def greet(): |
[K][W] |
def greet |
def add(a, b): |
[K][W][B][B][W][B][W] |
def add pass variable a variable b |
def power(base, exp=2): |
[K][W][B][B][W][B][W][O][B][W] |
def power pass variable base variable exp equals digit two |
def variable_args(*args): |
[K][W][W][B][B][W] |
def variable args pass tuple args |
def keyword_args(**kwargs): |
[K][W][W][B][B][W] |
def keyword args pass dictionary kwargs |
greet() |
[B][W] |
call greet |
int(num_str) |
[B][W][B][B][W][W] |
call int pass variable num str |
result = f(*args) |
[W][O][B][W][B][B][B][W] |
result equals call f pass list unpack args |
result = f(**kwargs) |
[W][O][B][W][B][B][B][W] |
result equals call f pass dictionary unpack kwargs |
| Python | KS | KVI |
|---|---|---|
class Person: |
[K][W] |
class Person |
class Dog(Animal): |
[K][W][B][B][W] |
class Dog pass variable Animal |
def __init__(self, name): |
[W][B][K][B][W][B][B][W][B][W] |
1 tab def hook init pass variable self variable name |
def greet(self): |
[W][B][K][W][B][B][W] |
1 tab def greet pass variable self |
self.name = name |
[B][W][B][W][O][B][W] |
variable self attribute name equals variable name |
name = person.name |
[W][O][B][W][B][W] |
name equals variable person attribute name |
cat.make_sound() |
[W][B][W][W] |
cat method make sound |
| Python | KS | KVI |
|---|---|---|
customer = {'name': 'Alice', 'age': 30} |
[W][O][B][B][W][B][B][W][B][B][W][B][B][W] |
customer equals key string name value string Alice key string age value digit thirty |
my_dict["c"] = 3 |
[B][W][W][B][B][W][O][B][W] |
variable my dict key string c equals digit three |
customer['age'] |
[W][B][B][W] |
customer key string age |
| Python | KS | KVI |
|---|---|---|
message = f"My name is {name}" |
[W][O][B][B][W][W][W][B][B][W] |
message equals f-string string My name is formatting variable name |
return f"Hello {self.name}" |
[K][B][B][W][B][B][W][B][W] |
return f-string string Hello formatting variable self attribute name |
f"{price:.2f}" |
[B][B][W][B][B][W][W] |
formatting variable price precision point 2 |
| Python | KS | KVI |
|---|---|---|
x = 10 (1 indent) |
[W][B][W][O][B][W] |
1 tab x equals digit ten |
print(x) (2 indents) |
[W][B][K][B][W] |
2 tab print variable x |
| Python | KS | KVI |
|---|---|---|
try: |
[K] |
try |
except ZeroDivisionError: |
[K][B][W][W][W] |
except type zero division error |
except ValueError as e: |
[K][B][W][W][K][B][W] |
except type value error as variable e |
| Python | KS | KVI |
|---|---|---|
with open("test.txt", "w") as f: |
[K][B][W][B][B][W][W][W][B][W][K][B][W] |
with call open pass string test dot txt string w as variable f |
| Python | KS | KVI |
|---|---|---|
square = lambda x: x**2 |
[W][O][K][B][W][B][B][W][O][B][W] |
square equals lambda variable x expression variable x power digit two |
even_numbers = list(filter(lambda x: x % 2 == 0, numbers)) |
[W][W][O][B][B][B][B][W][B][K][B][W][B][B][W][O][B][W][O][B][W][B][B][W] |
even numbers equals call list pass call filter pass lambda variable x expression variable x modulo digit two is equal digit zero pass variable numbers |
| Python | KS | KVI |
|---|---|---|
[x * 2 for x in range(5)] |
[B][B][W][O][B][W][K][B][W][K][B][W][B][B][W] |
list variable x times digit two for variable x in call range pass digit five |
{x for x in range(5)} |
[B][B][W][K][B][W][K][B][W][B][B][W] |
set variable x for variable x in call range pass digit five |
[Person(n, a) for n, a in zip(names, ages)] |
[B][B][W][B][B][W][B][W][K][B][W][B][W][K][B][W][B][B][W][B][W] |
list call Person pass variable n variable a for variable n variable a in call zip pass variable names variable ages |
| Python | KS | KVI |
|---|---|---|
num, _, last = (1, 2, 3) |
[B][W][B][B][W][O][B][B][W][B][W][B][W] |
variable num ignore variable last equals tuple digit one digit two digit three |
for _ in range(3): |
[K][B][K][B][W][B][B][W] |
for ignore in call range pass digit three |
LHS vs RHS distinction: Left-hand side names always emit plain [W] tokens, never prefixed with [B]variable. The [B]variable prefix is used only on the right-hand side or inside expressions.
x = y # x → [W] (LHS, no prefix)
# y → [B]variable [W]y (RHS, typed)Snake_case splitting: Variable names with underscores split into separate [W] tokens. my_list → [W]my [W]list. Note: is in is_valid is [W], not [K], because it is part of a variable name.
Number verbalization: Numbers up to 100 are verbalized; larger numbers pass through as digits. 10 → ten, 50 → fifty, 993 → 993.
Multi-word operators: Some operators produce one [O] tag but multiple KVI words:
| Python | KS tag | KVI phrase |
|---|---|---|
== |
[O] |
is equal (2 words) |
/= |
[O] |
divided equal (2 words) |
>= |
[O] |
greater or equal (3 words) |
// |
[O] |
floor divided by (3 words) |
Inter-argument pass rule: Plain typed args share the opening [B]pass. A fresh [B]pass is emitted only after a lambda argument:
filter(lambda x: x > 0, numbers)
→ call filter pass lambda variable x expression variable x greater than digit zero pass variable numbers| Word | As [K]
|
As [W]
|
|---|---|---|
is |
Standalone operator between two values | Part of a variable name (is_valid) |
list |
Collection base-word in RHS context | Part of a variable name (my_list) on LHS |
True/False/None
|
Always [K], Python keywords |
Never [W]
|
print |
Always [K] in Kencode |
Never [W]
|
Accessibility, Removes all special characters and punctuation from programming. Fully compatible with voice dictation, text-to-speech, and alternative input devices. Reduces cognitive load by separating what a token is from what it means.
Clarity and Learnability, Every statement becomes a readable English sentence. The [B] base-word system makes data types and structure explicit. KS patterns provide a visual grammar, learners can see structural patterns before mastering syntax.
Completeness, Full coverage of Python including variables, operators, control flow, functions, classes, OOP, dictionaries, collections, comprehensions, lambdas, f-strings, exception handling, file I/O, imports, and more. Bidirectional with no information lost in either direction.
Flexibility, Works as a standalone command-line tool, a web API, or an importable library. The KS regex rule is language-agnostic, the same four-token system could extend to other programming languages.
Kencode is introduced and formally described in the following peer-reviewed research paper. If you use Kencode in your research, teaching, software, or any published work, please cite the original paper.
@article{Alkhaldi2025Kencode,
author = {Khalid Alkhaldi and Asrar Qassem and Stephanie Ludi},
title = {Kencode: Advancing Voice-Based Programming Through an Innovative,
Standardized, and Taxonomic Structuring Approach},
journal = {Journal of Visual Language and Computing},
year = {2025},
pages = {8--17},
doi = {10.18293/JVLC2025-N3-079},
url = {http://ksiresearch.org/jvlc/journal/JVLC2025N3/JVLC079.pdf}
}Note: If you publish work that builds upon, extends, or evaluates Kencode, the authors welcome notification. The tool is provided freely for educational, research, and accessibility purposes in the spirit of the original paper's mission to advance voice-based and accessible programming.
Kencode © 2025-present by Khalid Alkhaldi is licensed under CC BY-NC-SA 4.0