advanced features

This commit is contained in:
tcsenpai 2025-03-02 22:14:19 +01:00
parent 849698bcee
commit 503c1236cd
7 changed files with 780 additions and 57 deletions

13
LICENSE.md Normal file
View File

@ -0,0 +1,13 @@
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.

225
README.md Normal file
View File

@ -0,0 +1,225 @@
# Scripting Language Factory
A powerful tool for creating, running, and managing custom programming languages based on any slang, meme terminology, or domain-specific vocabulary you prefer.
## Overview
This project allows you to define your own programming language syntax by mapping custom keywords to Python equivalents. It provides a complete environment for working with your custom language, including:
- Transpilation between your language and Python
- Direct execution of your language scripts
- Interactive REPL for development
- Compilation to Python bytecode
- Extensive customization options
## Installation
1. Clone this repository:
```
git clone https://github.com/yourusername/scripting-language-factory.git
cd scripting-language-factory
```
2. No additional dependencies required beyond Python 3.6+
## Quick Start
1. Create a default mapping file:
```
python transpiler.py create-mapping my_mapping.json
```
2. Write a script in your custom language (e.g., `hello.ski`):
```
ohio math
skibidi say_hello(name):
bussin(f"What's good, {name}!")
rizz f"Hello function executed for {name}"
yeet main_character == "__main__":
say_hello("fam")
```
3. Run your script:
```
python transpiler.py run hello.ski -c my_mapping.json
```
## Command Reference
### Create a Mapping File
```
python transpiler.py create-mapping filename.json
```
This creates a JSON file with default keyword mappings that you can customize.
### Transpile a File
```
python transpiler.py transpile input.ski -o output.py -c my_mapping.json
```
Convert your custom language to Python. Use the `-r` flag to convert from Python back to your custom language.
### Run a Script
```
python transpiler.py run script.ski -c my_mapping.json [args...]
```
Execute a script written in your custom language. Add `--debug` to see the transpiled Python code.
### Start the REPL
```
python transpiler.py repl -c my_mapping.json
```
Launch an interactive Read-Eval-Print Loop for your custom language.
### Compile to Bytecode
```
python transpiler.py compile script.ski -o output_dir -k -c my_mapping.json
```
Compile your custom language to Python bytecode (.pyc files). The `-k` flag keeps the intermediate Python file.
## Customizing Your Language
Edit the mapping file to define your own language syntax. The file has a structured format:
```json
{
"keywords": {
"skibidi": "def",
"toilet": "class",
"bussin": "print",
"rizz": "return",
...
},
"special_patterns": {
"no\\s+shot": "assert",
"on\\s+god": "global",
"spill\\s+the\\s+tea": "raise Exception",
"ratio\\s+(\\w+)": "del \\1"
},
"language_info": {
"name": "YourLanguage",
"version": "1.0.0",
"description": "Your custom language description",
"file_extension": ".yourlang"
}
}
```
- **keywords**: Simple word-to-word mappings
- **special_patterns**: Regular expressions for more complex syntax patterns
- **language_info**: Metadata about your language
You can add as many mappings as you want, including slang, meme terms, or domain-specific vocabulary.
## Special Syntax Features
The transpiler supports special multi-word phrases and patterns:
- `no shot <condition>``assert <condition>`
- `on god <variable>``global <variable>`
- `spill the tea``raise Exception`
- `ratio <variable>``del <variable>`
## Example
Here's a sample program in our default "meme language":
```
ohio math
ohio random simp rng
on god counter
counter = 0
toilet RizzCalculator(npc):
skibidi villain_arc(goated, name="Rizz Master"):
goated.name = name
goated.rizz_level = 0
girlboss
skibidi rizz_level(goated):
rizz goated.rizz_level
sigma
skibidi get_random_rizz():
rizz rng.randint(1, 100)
skibidi add_rizz(goated, amount):
finna:
goated.rizz_level += amount
rizz goated.rizz_level
bruh L_plus_ratio simp e:
bussin(f"L + ratio: {e}")
rizz mid
yeet main_character == "__main__":
calculator = RizzCalculator("Rizzy McRizzface")
fr i bet range(5):
random_rizz = RizzCalculator.get_random_rizz()
calculator.add_rizz(random_rizz)
counter += 1
bussin(f"Final rizz level: {calculator.rizz_level}")
```
## Advanced Features
- **Indentation Handling**: The transpiler automatically fixes indentation in the generated Python code.
- **Decorator Support**: Properly handles Python decorators like `@property` and `@staticmethod`.
- **Error Reporting**: Provides helpful debugging information when errors occur.
- **Command History**: The REPL maintains command history between sessions.
## Creating Your Own Language
1. Start with the default mapping file
2. Replace keywords with your preferred terms
3. Add new mappings for additional Python features
4. Create special syntax patterns for complex transformations
5. Write scripts in your new language
6. Share your language with others by distributing your mapping file
## Troubleshooting
If you encounter errors:
1. Use the `--debug` flag to see the transpiled Python code:
```
python transpiler.py run script.ski --debug -c my_mapping.json
```
2. Transpile to Python and inspect the code:
```
python transpiler.py transpile script.ski -o debug.py -c my_mapping.json
```
3. Check for syntax errors in your custom language script
## Contributing
Contributions are welcome! Feel free to:
- Add support for more Python features
- Improve error handling and debugging
- Create pre-defined language mappings
- Enhance the REPL experience
## License
[LICENSE.md](LICENSE.md)
## Acknowledgments
This project was inspired by the creativity of internet slang and meme culture, and the flexibility of the Python programming language.

View File

@ -1,26 +0,0 @@
ohio math
skibidi add_numbers(a, b):
rizz a + b
toilet Calculator:
skibidi __init__(self):
self.result = 0
skibidi calculate(self, x, y):
finna:
self.result = add_numbers(x, y)
bussin(f"Result: {self.result}")
rizz self.result
bruh Exception as e:
bussin(f"Error: {e}")
rizz cap
yeet __name__ == "__main__":
calc = Calculator()
fr i in range(1, 5):
bussin(f"Adding {i} and {i*2}")
calc.calculate(i, i*2)
based open("output.txt", "w") as f:
f.write("Calculations complete!")

View File

@ -1,17 +0,0 @@
{
"skibidi": "def",
"toilet": "class",
"ohio": "import",
"rizz": "return",
"bussin": "print",
"fr": "for",
"no_cap": "True",
"cap": "False",
"yeet": "if",
"sus": "else",
"vibe_check": "while",
"finna": "try",
"bruh": "except",
"slay": "lambda",
"based": "with"
}

78
rizzlang/example.ski Normal file
View File

@ -0,0 +1,78 @@
ohio math
ohio random simp rng
on god counter
counter = 0 # Initialize the counter
skibidi calculate_rizz(x, y):
vibe_check x < 10:
x += 1
bussin(f"Increasing rizz to {x}")
yeet y > 20:
karen ValueError("Too much rizz")
sus:
rizz x * y
toilet RizzCalculator(npc):
skibidi villain_arc(goated, name="Rizz Master"):
goated.name = name
goated.rizz_level = 0
girlboss
skibidi rizz_level(goated):
rizz goated.rizz_level
sigma
skibidi get_random_rizz():
rizz rng.randint(1, 100)
skibidi add_rizz(goated, amount):
finna:
goated.rizz_level += amount
yeet goated.rizz_level > 100:
bussin("MAXIMUM RIZZ ACHIEVED!")
goated.rizz_level = 100
rizz goated.rizz_level
bruh L_plus_ratio simp e:
bussin(f"L + ratio: {e}")
rizz mid
plot_twist:
bussin("Rizz calculation complete")
yeet main_character == "__main__":
no shot 2 + 2 == 4, "Math is working"
calculator = RizzCalculator("Rizzy McRizzface")
drip stats = {
"name": calculator.name,
"initial_rizz": calculator.rizz_level
}
glizzy rizz_levels = []
fr i bet range(5):
random_rizz = RizzCalculator.get_random_rizz()
bussin(f"Got random rizz: {random_rizz}")
calculator.add_rizz(random_rizz)
rizz_levels.append(calculator.rizz_level)
counter += 1 # Increment counter
bussin(f"Final rizz levels: {rizz_levels}")
bussin(f"Counter value: {counter}")
yeet calculator.rizz_level > 50:
bussin("High rizz achieved!")
sus:
bussin("Need more rizz...")
# Demonstrate special syntax
yeet counter > 3: # Changed from 10 to 3 so it will be true
bussin("Deleting counter...")
ratio counter # Delete counter
finna:
bussin(counter) # This will fail since counter is deleted
bruh NameError:
bussin("Counter successfully deleted!")
spill the tea # Raise exception

68
rizzlang/mapping.json Normal file
View File

@ -0,0 +1,68 @@
{
"keywords": {
"skibidi": "def",
"toilet": "class",
"ohio": "import",
"rizz": "return",
"bussin": "print",
"fr": "for",
"no_cap": "True",
"cap": "False",
"yeet": "if",
"sus": "else",
"vibe_check": "while",
"finna": "try",
"bruh": "except",
"slay": "lambda",
"based": "with",
"sheesh": "pass",
"mid": "None",
"goated": "self",
"npc": "object",
"glizzy": "list",
"drip": "dict",
"bet": "in",
"rent_free": "yield",
"chad": "super",
"karen": "raise",
"boomer": "break",
"zoomer": "continue",
"stan": "from",
"simp": "as",
"cringe": "assert",
"touch_grass": "exit",
"down_bad": "False",
"up_good": "True",
"ong": "not",
"lowkey": "nonlocal",
"highkey": "global",
"main_character": "__main__",
"villain_arc": "__init__",
"plot_twist": "finally",
"gaslighting": "isinstance",
"gatekeeping": "issubclass",
"girlboss": "property",
"sigma": "staticmethod",
"alpha": "classmethod",
"beta": "abstractmethod",
"L_plus_ratio": "Exception",
"skill_issue": "ValueError",
"cope": "TypeError",
"seethe": "KeyError",
"mald": "IndexError"
},
"special_patterns": {
"no\\s+shot": "assert",
"on\\s+god": "global",
"slide\\s+into\\s+(\\w+)": "import \\1",
"spill\\s+the\\s+tea": "raise Exception",
"ratio\\s+(\\w+)": "del \\1"
},
"language_info": {
"name": "RizzLang",
"version": "1.0.0",
"description": "A meme-based programming language",
"file_extension": ".ski",
"author": "Scripting Language Factory"
}
}

View File

@ -2,12 +2,34 @@ import json
import re
import argparse
import os
import sys
import tempfile
import subprocess
import readline # For better REPL experience
import py_compile
import shutil
from pathlib import Path
class Transpiler:
def __init__(self, mapping_file):
"""Initialize the transpiler with a JSON mapping file."""
with open(mapping_file, 'r') as f:
self.mapping = json.load(f)
mapping_data = json.load(f)
# Handle structured mapping format
if isinstance(mapping_data, dict) and "keywords" in mapping_data:
self.mapping = mapping_data.get("keywords", {})
else:
# Convert legacy format to structured format
self.mapping = mapping_data
print("Warning: Using legacy mapping format. Consider updating to structured format.", file=sys.stderr)
special_patterns_raw = mapping_data.get("special_patterns", {})
# Convert string patterns to actual regex patterns
self.special_patterns = {}
for pattern_str, replacement in special_patterns_raw.items():
self.special_patterns[pattern_str] = replacement
# Create reverse mapping for Python to custom language
self.reverse_mapping = {v: k for k, v in self.mapping.items()}
@ -19,19 +41,83 @@ class Transpiler:
# Create regex patterns for word boundaries
self.patterns = {k: re.compile(r'\b' + re.escape(k) + r'\b') for k in self.sorted_keywords}
self.reverse_patterns = {k: re.compile(r'\b' + re.escape(k) + r'\b') for k in self.sorted_reverse_keywords}
# Compile special patterns
self.compiled_special_patterns = {re.compile(k): v for k, v in self.special_patterns.items()}
def to_python(self, source_code):
"""Convert custom language to Python."""
result = source_code
# Apply special patterns first
for pattern, replacement in self.compiled_special_patterns.items():
result = pattern.sub(replacement, result)
# Then apply regular word replacements
for keyword in self.sorted_keywords:
result = self.patterns[keyword].sub(self.mapping[keyword], result)
# Fix common syntax issues
# Fix decorators - first convert standalone decorators to proper Python syntax
result = re.sub(r'@property\s*$', r'@property', result)
result = re.sub(r'@staticmethod\s*$', r'@staticmethod', result)
result = re.sub(r'@classmethod\s*$', r'@classmethod', result)
# Fix main_character check
result = result.replace('if __main__ ==', 'if __name__ ==')
# Fix list and dict literals
result = result.replace('list ', '')
result = result.replace('dict ', '')
# Fix L_plus_ratio exception
result = result.replace('L_plus_del', 'Exception')
# Fix indentation
lines = result.split('\n')
properly_indented_lines = []
for line in lines:
# Count leading spaces
leading_spaces = len(line) - len(line.lstrip())
# Calculate proper indentation level (4 spaces per level)
indent_level = leading_spaces // 4
# Create properly indented line
properly_indented_lines.append(' ' * indent_level + line.lstrip())
result = '\n'.join(properly_indented_lines)
return result
def from_python(self, python_code):
"""Convert Python to custom language."""
result = python_code
# Apply regular word replacements first
for keyword in self.sorted_reverse_keywords:
result = self.reverse_patterns[keyword].sub(self.reverse_mapping[keyword], result)
# Then apply special patterns in reverse
for pattern, replacement in self.compiled_special_patterns.items():
# Create reverse pattern
reverse_pattern = re.compile(r'\b' + re.escape(replacement) + r'\b')
# Extract capture groups if any
match = re.search(r'\\(\d+)', pattern.pattern)
if match:
# If there are capture groups, we need to handle them specially
capture_group = int(match.group(1))
# Find all matches of the reverse pattern
matches = reverse_pattern.finditer(result)
for m in matches:
# Extract the captured value
captured = m.group(capture_group) if capture_group <= len(m.groups()) else ""
# Replace with the original pattern format
original_format = pattern.pattern.replace(f'\\{capture_group}', captured)
result = result.replace(m.group(0), original_format)
else:
# Simple replacement
result = reverse_pattern.sub(pattern.pattern, result)
return result
def transpile_file(self, input_file, output_file=None, reverse=False):
@ -50,24 +136,320 @@ class Transpiler:
return f"Transpiled to {output_file}"
else:
return result
def execute_code(self, input_file, args=None, debug=False):
"""Execute a custom language file by transpiling to Python and running it."""
# Create a temporary file for the transpiled Python code
with tempfile.NamedTemporaryFile(suffix='.py', delete=False) as temp_file:
temp_filename = temp_file.name
try:
# Transpile the input file to the temporary Python file
self.transpile_file(input_file, temp_filename)
# If debug mode is enabled, print the transpiled Python code
if debug:
with open(temp_filename, 'r') as f:
print("=== Transpiled Python Code ===")
print(f.read())
print("=============================")
# Prepare command to run the Python file
cmd = [sys.executable, temp_filename]
if args:
cmd.extend(args)
# Execute the Python file
result = subprocess.run(cmd, capture_output=True, text=True)
# Print output and errors
if result.stdout:
print(result.stdout, end='')
if result.stderr:
print(result.stderr, end='', file=sys.stderr)
# If there's a syntax error, try to map it back to the original file
if "SyntaxError" in result.stderr:
print("\n=== Debugging Information ===")
print(f"The error occurred in the transpiled Python code. To debug:")
print(f"1. Run with debug flag: python transpiler.py run {input_file} --debug")
print(f"2. Or transpile to inspect: python transpiler.py transpile {input_file} -o debug.py")
print("==============================")
return result.returncode
finally:
# Clean up the temporary file unless in debug mode
if os.path.exists(temp_filename) and not debug:
os.remove(temp_filename)
def compile_code(self, input_file, output_dir=None, keep_py=False):
"""Compile a custom language file to Python bytecode."""
# Get the base name of the input file
base_name = os.path.basename(input_file)
name_without_ext = os.path.splitext(base_name)[0]
# Determine output directory
if output_dir is None:
output_dir = os.path.dirname(input_file) or '.'
# Create output directory if it doesn't exist
os.makedirs(output_dir, exist_ok=True)
# Create a temporary Python file
py_file = os.path.join(output_dir, f"{name_without_ext}.py")
try:
# Transpile the input file to Python
self.transpile_file(input_file, py_file)
# Compile the Python file to bytecode
py_compile.compile(py_file, cfile=os.path.join(output_dir, f"{name_without_ext}.pyc"))
print(f"Compiled to {os.path.join(output_dir, name_without_ext + '.pyc')}")
# Optionally remove the intermediate Python file
if not keep_py and os.path.exists(py_file):
os.remove(py_file)
return True
except Exception as e:
print(f"Compilation error: {e}", file=sys.stderr)
# Clean up in case of error
if os.path.exists(py_file) and not keep_py:
os.remove(py_file)
return False
def start_repl(self):
"""Start a REPL (Read-Eval-Print Loop) for the custom language."""
print(f"Custom Language REPL (Python {sys.version.split()[0]})")
print("Type 'exit()' or 'quit()' to exit")
# Set up readline history
histfile = os.path.join(os.path.expanduser("~"), ".custom_lang_history")
try:
readline.read_history_file(histfile)
readline.set_history_length(1000)
except FileNotFoundError:
pass
# Create a temporary module for the REPL
temp_module = {}
# Keep track of indentation level
indent_level = 0
buffer = []
while True:
try:
# Determine prompt based on indentation
if indent_level > 0:
prompt = "... " + " " * indent_level
else:
prompt = ">>> "
# Get input from user
line = input(prompt)
# Check for exit commands
if line.strip() in ('exit()', 'quit()') and indent_level == 0:
break
# Add line to buffer
buffer.append(line)
# Update indentation level
if line.endswith(':'):
indent_level += 1
elif line.strip() == '' and indent_level > 0:
indent_level -= 1
# If we're back to zero indentation, execute the buffer
if indent_level == 0 and buffer:
# Join the buffer into a single string
code_to_execute = '\n'.join(buffer)
buffer = []
# Transpile the custom code to Python
python_code = self.to_python(code_to_execute)
try:
# Execute the Python code
result = eval(python_code, temp_module)
if result is not None:
print(repr(result))
except SyntaxError:
try:
# If it's not an expression, execute it as a statement
exec(python_code, temp_module)
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
except Exception as e:
print(f"Error: {e}", file=sys.stderr)
except KeyboardInterrupt:
print("\nKeyboardInterrupt")
buffer = []
indent_level = 0
except EOFError:
print("\nExiting...")
break
# Save readline history
try:
readline.write_history_file(histfile)
except:
pass
def main():
parser = argparse.ArgumentParser(description='Transpile between custom language and Python')
parser.add_argument('input_file', help='Input file to transpile')
parser.add_argument('-o', '--output', help='Output file (if not specified, prints to stdout)')
parser.add_argument('-m', '--mapping', required=True, help='JSON mapping file')
parser.add_argument('-r', '--reverse', action='store_true', help='Transpile from Python to custom language')
parser = argparse.ArgumentParser(description='Transpile, execute, or compile custom language files')
# Create subparsers for different commands
subparsers = parser.add_subparsers(dest='command', help='Command to run')
# Transpile command
transpile_parser = subparsers.add_parser('transpile', help='Transpile between custom language and Python')
transpile_parser.add_argument('input_file', help='Input file to transpile')
transpile_parser.add_argument('-o', '--output', help='Output file (if not specified, prints to stdout)')
transpile_parser.add_argument('-r', '--reverse', action='store_true', help='Transpile from Python to custom language')
# Execute command
execute_parser = subparsers.add_parser('run', help='Execute a custom language file')
execute_parser.add_argument('input_file', help='Input file to execute')
execute_parser.add_argument('args', nargs='*', help='Arguments to pass to the program')
execute_parser.add_argument('--debug', action='store_true', help='Show transpiled Python code for debugging')
# Compile command
compile_parser = subparsers.add_parser('compile', help='Compile a custom language file to Python bytecode')
compile_parser.add_argument('input_file', help='Input file to compile')
compile_parser.add_argument('-o', '--output-dir', help='Output directory for compiled files')
compile_parser.add_argument('-k', '--keep-py', action='store_true', help='Keep intermediate Python file')
# REPL command
repl_parser = subparsers.add_parser('repl', help='Start a REPL for the custom language')
# Create mapping command
create_parser = subparsers.add_parser('create-mapping', help='Create a new mapping file with default values')
create_parser.add_argument('output_file', help='Output file for the mapping')
# Common arguments
parser.add_argument('-c', '--config', help='JSON mapping file (defaults to mapping.json in current directory)')
args = parser.parse_args()
transpiler = Transpiler(args.mapping)
# If no command is specified, show help
if not args.command:
parser.print_help()
return
if args.output:
result = transpiler.transpile_file(args.input_file, args.output, args.reverse)
print(result)
else:
result = transpiler.transpile_file(args.input_file, reverse=args.reverse)
print(result)
# Handle create-mapping command
if args.command == 'create-mapping':
create_default_mapping(args.output_file)
print(f"Created default mapping file at {args.output_file}")
return
# Ensure mapping file is provided for other commands
if not args.config:
# Try to find a mapping.json file in the current directory
if os.path.exists('mapping.json'):
args.config = 'mapping.json'
else:
print("Error: Mapping file is required. Use -c/--config option or create a mapping.json file in the current directory.", file=sys.stderr)
return 1
# Create transpiler
transpiler = Transpiler(args.config)
# Handle commands
if args.command == 'transpile':
if args.output:
result = transpiler.transpile_file(args.input_file, args.output, args.reverse)
print(result)
else:
result = transpiler.transpile_file(args.input_file, reverse=args.reverse)
print(result)
elif args.command == 'run':
return transpiler.execute_code(args.input_file, args.args, args.debug)
elif args.command == 'compile':
transpiler.compile_code(args.input_file, args.output_dir, args.keep_py)
elif args.command == 'repl':
transpiler.start_repl()
def create_default_mapping(filename):
"""Create a default mapping file with meme/slang terms."""
default_mapping = {
"keywords": {
"skibidi": "def",
"toilet": "class",
"ohio": "import",
"rizz": "return",
"bussin": "print",
"fr": "for",
"no_cap": "True",
"cap": "False",
"yeet": "if",
"sus": "else",
"vibe_check": "while",
"finna": "try",
"bruh": "except",
"slay": "lambda",
"based": "with",
"sheesh": "pass",
"mid": "None",
"goated": "self",
"npc": "object",
"glizzy": "list",
"drip": "dict",
"bet": "in",
"rent_free": "yield",
"chad": "super",
"karen": "raise",
"boomer": "break",
"zoomer": "continue",
"stan": "from",
"simp": "as",
"cringe": "assert",
"touch_grass": "exit",
"down_bad": "False",
"up_good": "True",
"ong": "not",
"lowkey": "nonlocal",
"highkey": "global",
"main_character": "__main__",
"villain_arc": "__init__",
"plot_twist": "finally",
"gaslighting": "isinstance",
"gatekeeping": "issubclass",
"girlboss": "property",
"sigma": "staticmethod",
"alpha": "classmethod",
"beta": "abstractmethod",
"L_plus_ratio": "Exception",
"skill_issue": "ValueError",
"cope": "TypeError",
"seethe": "KeyError",
"mald": "IndexError"
},
"special_patterns": {
"no\\s+shot": "assert",
"on\\s+god": "global",
"slide\\s+into\\s+(\\w+)": "import \\1",
"spill\\s+the\\s+tea": "raise Exception",
"ratio\\s+(\\w+)": "del \\1"
},
"language_info": {
"name": "RizzLang",
"version": "1.0.0",
"description": "A meme-based programming language",
"file_extension": ".ski",
"author": "Scripting Language Factory"
}
}
with open(filename, 'w') as f:
json.dump(default_mapping, f, indent=4)
if __name__ == "__main__":
main()
sys.exit(main() or 0)