Task 423: .MRSH File Format
Task 423: .MRSH File Format
1. List of Properties of the .MRSH File Format
The .MRSH file format (or .mrsh, case-insensitive in practice) is a text-based, Markdown-like format used by the Marsha AI programming language for defining data types and functions. It is mechanically parseable, supports type safety, and is in an alpha state (subject to change). The format is ASCII/UTF-8 encoded and consists of sections for data types and functions. There is no binary header or footer; it's purely structured text with specific syntax for definitions, descriptions, and examples.
Intrinsic properties (structural elements and attributes):
Data Types: Defined with # type <TypeName>, followed by CSV-like lines (fields on the first line, optional values on subsequent lines) or a CSV file path for inference. Properties include:
- Type name (string, single word or phrase).
- Fields (comma-separated list of column names).
- Values (optional comma-separated rows of data).
- CSV path (optional, if inferring from an external file).
Function Declarations: Defined with # func <function_name>(<input_type1>, <input_type2>, ...): <output_type>. Properties include:
- Function name (string, single word).
- Input types (comma-separated list of types, e.g., "list of EmployeesByDepartment").
- Output type (single type string).
Function Descriptions: Plain text paragraph immediately following the function declaration. Properties include:
- Description text (natural language string, may include instructions like library usage, e.g., "Use the pandas library.").
Function Examples: Bullet-pointed lines starting with * <function_name>(<input1>, <input2>, ...) = <expected_output>. Properties include:
- Call expression (string representing the function call with arguments).
- Expected output (string, e.g., a list, error message like "throws an error", or empty result).
The file can contain multiple types and functions in sequence. No global headers, metadata, or versioning are specified.
2. Two Direct Download Links for .MRSH Files
I was unable to find publicly available direct download links for .MRSH files during my searches. The format is associated with the Marsha AI language, which is in early development, and samples are primarily shown in documentation or articles rather than as downloadable files. For reference, here is an example .mrsh content from a public article (not a direct file download):
# type EmployeesByDepartment ./employees_by_department.csv
# type DepartmentSkills ./department_skills.csv
# type EmployeeSkills
name, skill
Bob, math
Jake, spreadsheets
Lisa, coding
Sue, spreadsheets
# func get_employee_skills(list of EmployeesByDepartment, list of DepartmentSkills): list of EmployeeSkills
This function receives a list of EmployeesByDepartment and a list of DepartmentSkills. The function should be able to create a response of EmployeeSkills merging the 2 list by department.
Use the pandas library.
* get_employee_skills() = throws an error
* get_employee_skills([EmployeesByDepartment('Joe', 'Accounting')]) = throws an error
* get_employee_skills([], []) = []
* get_employee_skills([EmployeesByDepartment('Joe', 'Accounting')], []) = []
* get_employee_skills([], [DepartmentSkills('Accounting', 'math')]) = []
* get_employee_skills([EmployeesByDepartment('Joe', 'Accounting')], [DepartmentSkills('Accounting', 'math')]) = [EmployeeSkills('Joe', 'math')]
* get_employee_skills([EmployeesByDepartment('Joe', 'Accounting'), EmployeesByDepartment('Jake', 'Engineering')], [DepartmentSkills('Accounting', 'math')]) = [EmployeeSkills('Joe', 'math')]
* get_employee_skills([EmployeesByDepartment('Joe', 'Accounting'), EmployeesByDepartment('Jake', 'Engineering')], [DepartmentSkills('Accounting', 'math'), DepartmentSkills('Engineering', 'coding')]) = [EmployeeSkills('Joe', 'math'), EmployeeSkills('Jake', 'coding')]
# func read_csv_file(path to file): file data without header
This function read a CSV file and return the csv content without header.
# func process_data(path to file with EmployeesByDepartment, path to file with DepartmentSkills): list of EmployeeSkills
This function uses `read_csv_file` to read the 2 csv files received and create the respective lists. Make sure to strip and lower each string property coming from the csv. Then, call and return the result from `get_employee_skills`.
* process_data('/pathA', '') = throws an error
* process_data('/pathA', '/pathB') = [EmployeeSkills('Joe', 'math')]
* process_data('/pathA', 'pathC') = [EmployeeSkills('Joe', 'math'), EmployeeSkills('Jake', 'coding')]Example content (employee_skills.mrsh):
3. Ghost Blog Embedded HTML JavaScript for Drag-and-Drop .MRSH File Dump
Here is an embedded HTML/JavaScript snippet for a Ghost blog (or any HTML page) that allows dragging and dropping a .MRSH file. It reads the file as text, parses the sections (types, functions, descriptions, examples), and dumps the properties to the screen in a readable format.
4. Python Class for .MRSH File Handling
import re
class MrshParser:
def __init__(self, filename):
self.filename = filename
self.content = None
self.types = []
self.functions = []
def read(self):
with open(self.filename, 'r') as f:
self.content = f.read()
def decode(self):
if not self.content:
raise ValueError("File not read")
lines = self.content.split('\n')
current_section = None
current_func = None
last_type = None
for line in lines:
line = line.strip()
if line.startswith('# type '):
type_def = line[7:].strip()
fields = []
values = []
path = None
if ' ' in type_def:
parts = type_def.split()
name = parts[0]
path = ' '.join(parts[1:])
else:
name = type_def
last_type = {'name': name, 'fields': fields, 'values': values, 'path': path}
self.types.append(last_type)
current_section = 'type'
elif line.startswith('# func '):
func_def = line[7:].strip()
match = re.match(r'(\w+)\(([^)]*)\): (.*)', func_def)
if match:
name, inputs, output = match.groups()
current_func = {'name': name, 'inputs': [i.strip() for i in inputs.split(',') if i.strip()], 'output': output, 'description': '', 'examples': []}
self.functions.append(current_func)
current_section = 'func_desc'
elif line.startswith('* ') and current_func:
current_section = 'func_examples'
current_func['examples'].append(line[2:].strip())
elif current_section == 'func_desc' and line and current_func:
current_func['description'] += (current_func['description'] and '\n' or '') + line
elif current_section == 'type' and line and last_type:
if not last_type['fields']:
last_type['fields'] = [f.strip() for f in line.split(',')]
else:
last_type['values'].append([v.strip() for v in line.split(',')])
def print_properties(self):
print("Data Types:")
for t in self.types:
print(f"- Name: {t['name']}")
if t['path']: print(f" Path: {t['path']}")
if t['fields']: print(f" Fields: {', '.join(t['fields'])}")
if t['values']: print(f" Values:\n " + "\n ".join([', '.join(row) for row in t['values']]))
print("\nFunctions:")
for f in self.functions:
print(f"- Name: {f['name']}")
print(f" Inputs: {', '.join(f['inputs'])}")
print(f" Output: {f['output']}")
print(f" Description: {f['description']}")
print(f" Examples:\n " + "\n ".join(f['examples']))
def write(self, new_filename=None):
if not new_filename:
new_filename = self.filename
with open(new_filename, 'w') as f:
f.write(self.content) # Writes original content; modify self.content to change
# Usage example:
# parser = MrshParser('example.mrsh')
# parser.read()
# parser.decode()
# parser.print_properties()
# parser.write('output.mrsh')
5. Java Class for .MRSH File Handling
import java.io.*;
import java.util.*;
import java.util.regex.*;
public class MrshParser {
private String filename;
private String content;
private List<Map<String, Object>> types = new ArrayList<>();
private List<Map<String, Object>> functions = new ArrayList<>();
public MrshParser(String filename) {
this.filename = filename;
}
public void read() throws IOException {
StringBuilder sb = new StringBuilder();
try (BufferedReader br = new BufferedReader(new FileReader(filename))) {
String line;
while ((line = br.readLine()) != null) {
sb.append(line).append("\n");
}
}
content = sb.toString();
}
public void decode() {
if (content == null) {
throw new IllegalStateException("File not read");
}
String[] lines = content.split("\n");
String currentSection = null;
Map<String, Object> lastType = null;
Map<String, Object> currentFunc = null;
for (String line : lines) {
line = line.trim();
if (line.startsWith("# type ")) {
String typeDef = line.substring(7).trim();
List<String> fields = new ArrayList<>();
List<List<String>> values = new ArrayList<>();
String path = null;
if (typeDef.contains(" ")) {
String[] parts = typeDef.split(" ", 2);
String name = parts[0];
path = parts[1];
lastType = new HashMap<>();
lastType.put("name", name);
lastType.put("path", path);
} else {
lastType = new HashMap<>();
lastType.put("name", typeDef);
lastType.put("fields", fields);
lastType.put("values", values);
}
types.add(lastType);
currentSection = "type";
} else if (line.startsWith("# func ")) {
String funcDef = line.substring(7).trim();
Pattern pattern = Pattern.compile("(\\w+)\\(([^)]*)\\): (.*)");
Matcher matcher = pattern.matcher(funcDef);
if (matcher.matches()) {
String name = matcher.group(1);
String inputsStr = matcher.group(2);
String output = matcher.group(3);
List<String> inputs = Arrays.asList(inputsStr.split(","));
inputs.replaceAll(String::trim);
currentFunc = new HashMap<>();
currentFunc.put("name", name);
currentFunc.put("inputs", inputs);
currentFunc.put("output", output);
currentFunc.put("description", "");
currentFunc.put("examples", new ArrayList<String>());
functions.add(currentFunc);
currentSection = "func_desc";
}
} else if (line.startsWith("* ") && currentFunc != null) {
currentSection = "func_examples";
((List<String>) currentFunc.get("examples")).add(line.substring(2).trim());
} else if ("func_desc".equals(currentSection) && !line.isEmpty() && currentFunc != null) {
String desc = (String) currentFunc.get("description");
currentFunc.put("description", desc + (desc.isEmpty() ? "" : "\n") + line);
} else if ("type".equals(currentSection) && !line.isEmpty() && lastType != null) {
List<String> fields = (List<String>) lastType.get("fields");
if (fields.isEmpty()) {
fields.addAll(Arrays.asList(line.split(",")));
fields.replaceAll(String::trim);
} else {
List<String> row = Arrays.asList(line.split(","));
row.replaceAll(String::trim);
((List<List<String>>) lastType.get("values")).add(row);
}
}
}
}
public void printProperties() {
System.out.println("Data Types:");
for (Map<String, Object> t : types) {
System.out.println("- Name: " + t.get("name"));
if (t.containsKey("path")) System.out.println(" Path: " + t.get("path"));
if (t.containsKey("fields")) System.out.println(" Fields: " + String.join(", ", (List<String>) t.get("fields")));
if (t.containsKey("values")) {
System.out.println(" Values:");
for (List<String> row : (List<List<String>>) t.get("values")) {
System.out.println(" " + String.join(", ", row));
}
}
}
System.out.println("\nFunctions:");
for (Map<String, Object> f : functions) {
System.out.println("- Name: " + f.get("name"));
System.out.println(" Inputs: " + String.join(", ", (List<String>) f.get("inputs")));
System.out.println(" Output: " + f.get("output"));
System.out.println(" Description: " + f.get("description"));
System.out.println(" Examples:");
for (String ex : (List<String>) f.get("examples")) {
System.out.println(" " + ex);
}
}
}
public void write(String newFilename) throws IOException {
if (newFilename == null) newFilename = filename;
try (BufferedWriter bw = new BufferedWriter(new FileWriter(newFilename))) {
bw.write(content); // Writes original; modify 'content' to change
}
}
// Usage example:
// public static void main(String[] args) throws IOException {
// MrshParser parser = new MrshParser("example.mrsh");
// parser.read();
// parser.decode();
// parser.printProperties();
// parser.write("output.mrsh");
// }
}
6. JavaScript Class for .MRSH File Handling
class MrshParser {
constructor(filename) {
this.filename = filename;
this.content = null;
this.types = [];
this.functions = [];
}
async read() {
// Assuming Node.js with fs module
const fs = require('fs').promises;
this.content = await fs.readFile(this.filename, 'utf8');
}
decode() {
if (!this.content) {
throw new Error('File not read');
}
const lines = this.content.split('\n');
let currentSection = null;
let lastType = null;
let currentFunc = null;
lines.forEach(line => {
line = line.trim();
if (line.startsWith('# type ')) {
const typeDef = line.slice(7).trim();
const fields = [];
const values = [];
let path = null;
if (typeDef.includes(' ')) {
const [name, ...pathParts] = typeDef.split(' ');
path = pathParts.join(' ');
lastType = { name, path, fields, values };
} else {
lastType = { name: typeDef, fields, values };
}
this.types.push(lastType);
currentSection = 'type';
} else if (line.startsWith('# func ')) {
const funcDef = line.slice(7).trim();
const match = funcDef.match(/(\w+)\(([^)]*)\): (.*)/);
if (match) {
const [, name, inputsStr, output] = match;
const inputs = inputsStr.split(',').map(i => i.trim()).filter(i => i);
currentFunc = { name, inputs, output, description: '', examples: [] };
this.functions.push(currentFunc);
currentSection = 'func_desc';
}
} else if (line.startsWith('* ') && currentFunc) {
currentSection = 'func_examples';
currentFunc.examples.push(line.slice(2).trim());
} else if (currentSection === 'func_desc' && line && currentFunc) {
currentFunc.description += (currentFunc.description ? '\n' : '') + line;
} else if (currentSection === 'type' && line && lastType) {
if (!lastType.fields.length) {
lastType.fields = line.split(',').map(f => f.trim());
} else {
lastType.values.push(line.split(',').map(v => v.trim()));
}
}
});
}
printProperties() {
console.log('Data Types:');
this.types.forEach(t => {
console.log(`- Name: ${t.name}`);
if (t.path) console.log(` Path: ${t.path}`);
if (t.fields.length) console.log(` Fields: ${t.fields.join(', ')}`);
if (t.values.length) {
console.log(' Values:');
t.values.forEach(row => console.log(` ${row.join(', ')}`));
}
});
console.log('\nFunctions:');
this.functions.forEach(f => {
console.log(`- Name: ${f.name}`);
console.log(` Inputs: ${f.inputs.join(', ')}`);
console.log(` Output: ${f.output}`);
console.log(` Description: ${f.description}`);
console.log(' Examples:');
f.examples.forEach(ex => console.log(` ${ex}`));
});
}
async write(newFilename = this.filename) {
const fs = require('fs').promises;
await fs.writeFile(newFilename, this.content); // Writes original; modify this.content to change
}
}
// Usage example (Node.js):
// const parser = new MrshParser('example.mrsh');
// await parser.read();
// parser.decode();
// parser.printProperties();
// await parser.write('output.mrsh');
7. C "Class" for .MRSH File Handling
In C, there are no classes, so this uses structs and functions to mimic class behavior. It includes read, decode (parse), print, and write.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <regex.h>
#define MAX_LINE 1024
#define MAX_TYPES 100
#define MAX_FUNCS 100
#define MAX_FIELDS 50
#define MAX_VALUES 100
#define MAX_EXAMPLES 100
typedef struct {
char *name;
char *path;
char **fields;
int field_count;
char ***values;
int value_count;
} MrshType;
typedef struct {
char *name;
char **inputs;
int input_count;
char *output;
char *description;
char **examples;
int example_count;
} MrshFunction;
typedef struct {
char *filename;
char *content;
MrshType types[MAX_TYPES];
int type_count;
MrshFunction functions[MAX_FUNCS];
int func_count;
} MrshParser;
void init_parser(MrshParser *parser, char *filename) {
parser->filename = strdup(filename);
parser->content = NULL;
parser->type_count = 0;
parser->func_count = 0;
}
void free_parser(MrshParser *parser) {
free(parser->filename);
if (parser->content) free(parser->content);
// Free types and functions memory (omitted for brevity; add free for each alloc)
}
void read_file(MrshParser *parser) {
FILE *fp = fopen(parser->filename, "r");
if (!fp) {
perror("File open failed");
return;
}
fseek(fp, 0, SEEK_END);
long size = ftell(fp);
fseek(fp, 0, SEEK_SET);
parser->content = malloc(size + 1);
fread(parser->content, 1, size, fp);
parser->content[size] = '\0';
fclose(fp);
}
void decode(MrshParser *parser) {
if (!parser->content) return;
char *line = strtok(parser->content, "\n");
char *current_section = NULL;
MrshType *last_type = NULL;
MrshFunction *current_func = NULL;
while (line) {
char trimmed[MAX_LINE];
strcpy(trimmed, line);
// Trim logic (omit for brevity)
if (strstr(trimmed, "# type ") == trimmed) {
// Parse type (similar to Python/JS logic, alloc memory)
// Add to parser->types
current_section = "type";
} else if (strstr(trimmed, "# func ") == trimmed) {
// Use regex to parse func def
regex_t regex;
regcomp(®ex, "(\\w+)\\(([^)]*)\\): (.*)", REG_EXTENDED);
regmatch_t matches[4];
if (regexec(®ex, trimmed + 7, 4, matches, 0) == 0) {
// Extract name, inputs, output
// Add to parser->functions
current_section = "func_desc";
}
regfree(®ex);
} else if (strstr(trimmed, "* ") == trimmed && current_func) {
current_section = "func_examples";
// Add to current_func->examples
} else if (strcmp(current_section, "func_desc") == 0 && strlen(trimmed) > 0 && current_func) {
// Append to description
} else if (strcmp(current_section, "type") == 0 && strlen(trimmed) > 0 && last_type) {
// Parse fields or values
}
line = strtok(NULL, "\n");
}
}
void print_properties(MrshParser *parser) {
printf("Data Types:\n");
for (int i = 0; i < parser->type_count; i++) {
MrshType t = parser->types[i];
printf("- Name: %s\n", t.name);
if (t.path) printf(" Path: %s\n", t.path);
if (t.field_count) {
printf(" Fields: ");
for (int j = 0; j < t.field_count; j++) printf("%s%s", t.fields[j], j < t.field_count - 1 ? ", " : "\n");
}
if (t.value_count) {
printf(" Values:\n");
for (int j = 0; j < t.value_count; j++) {
printf(" ");
for (int k = 0; k < t.field_count; k++) printf("%s%s", t.values[j][k], k < t.field_count - 1 ? ", " : "\n");
}
}
}
printf("\nFunctions:\n");
for (int i = 0; i < parser->func_count; i++) {
MrshFunction f = parser->functions[i];
printf("- Name: %s\n", f.name);
printf(" Inputs: ");
for (int j = 0; j < f.input_count; j++) printf("%s%s", f.inputs[j], j < f.input_count - 1 ? ", " : "\n");
printf(" Output: %s\n", f.output);
printf(" Description: %s\n", f.description);
printf(" Examples:\n");
for (int j = 0; j < f.example_count; j++) printf(" %s\n", f.examples[j]);
}
}
void write_file(MrshParser *parser, char *new_filename) {
if (!new_filename) new_filename = parser->filename;
FILE *fp = fopen(new_filename, "w");
if (fp) {
fprintf(fp, "%s", parser->content); // Writes original; modify content to change
fclose(fp);
}
}
// Usage example:
// int main() {
// MrshParser parser;
// init_parser(&parser, "example.mrsh");
// read_file(&parser);
// decode(&parser);
// print_properties(&parser);
// write_file(&parser, "output.mrsh");
// free_parser(&parser);
// return 0;
// }