Getting Started
I see you’ve decided to become even sillier. BIG mistake.
1) Download SillyScript
You can download SillyScript once I create SillyScript.
2) Create some SillyScript code
Save the following code into a file named list.silly:
1;
"This is a string";
false;
3) Convert your script to data
Finally, you can run the SillyScript executable to convert the script into a data format.
silly <script file path> <output file path>
So like this:
silly list.silly output.json
Syntax
The fundamentals of this language make it seem so useless and… silly. Just bear with it, it will make sense eventually.
Top-Level Syntax
All SillyScript code represents data. It can represent a list or dictionary.
While SillyScript can export to multiple data formats, JSON is the main one used in this documentation to represent how the structure of the language works.
List
The contents on the left side is an entirely valid SillyScript file.
| SillyScript | JSON |
|---|---|
|
This is an entire valid SillyScript file:
|
It is the equivalent of this JSON:
|
Dictionary
| SillyScript | JSON |
|---|---|
|
This is ALSO an entire valid SillyScript file:
|
It is the equivalent of this JSON:
|
Combination
SillyScript will automatically figure out if the file should be a List type of Dictionary type. These two types cannot be combined.
This is NOT a valid SillyScript file. The string must be labeled, or the labels must be removed from the number and boolean.
my_number: 1;
"This is a string";
myBool: false;
Lists and dictionaries can be mixed by adding them as sub-elements to each other using the proper syntax.
List
Use the blank colon syntax to create a new scope for a list.
:
1;
2;
3;
Dictionary
Use the blank colon syntax to create a new scope for a dictionary.
:
key1: 1;
something: 2;
bla: 3;
Combination
Here is an example of combining list and dictionaries and its equivalent in JSON:
| SillyScript | JSON |
|---|---|
|
A complicated structure in SillyScript.
|
What it represents in JSON.
|
Definitions
Definitions can be used to simplify common patterns.
Basic Syntax
A definition can be used to type specific data patterns.
def Wait(duration: int) -> dict:
type: 0;
duration: duration;
Calling this definition places the resulting data where the call occurs.
| SillyScript | JSON |
|---|---|
|
The SillyScript definition call:
|
The equivalent JSON:
|
Arguments
Definition arguments are provided as a list of NAME: TYPE combinations. See Types for more information on types.
Named Arguments
Arguments can also be passed by name. This allows only certain arguments to be used.
For example:
| SillyScript | JSON |
|---|---|
|
The SillyScript definition call:
|
The equivalent JSON:
|
Enums
Enums are collections of identifiers that can be used as types.
Basic Syntax
An enum can be declared using the enum keyword:
enum BreakfastFood:
pancake;
hash_brown;
burger;
By default, an enum identifier will generate as its index.
| SillyScript | JSON |
|---|---|
|
The SillyScript definition call:
|
The equivalent JSON:
|
Underlying Type
An enum can generate as other types. Simple add an -> TYPE after the enum name to dictate what type it’s converted to.
Currently only string and int are supported.
| SillyScript | JSON |
|---|---|
|
The SillyScript definition call:
|
The equivalent JSON:
|
Argument
An enum’s name can be used as an argument.
| SillyScript | JSON |
|---|---|
|
The SillyScript definition call:
|
The equivalent JSON:
|
Types
SillyScript is built on a handful of core-types.
Booleans
The bool type can only store two options: true or false.
| SillyScript | JSON |
|---|---|
|
SillyScript code:
|
The equivalent JSON:
|
Numbers
There are two number types: int and float. floats can have numbers with decimal places, ints must be integers.
| SillyScript | JSON |
|---|---|
|
SillyScript code:
|
The equivalent JSON:
|
Strings
The string type is a string of characters. At the current moment you can only use double-quotes for strings.
| SillyScript | JSON |
|---|---|
|
SillyScript code:
|
The equivalent JSON:
|
Null
Types can be assigned null to store nothing. When passing null to a typed entry, the type must be “nullable”. A type can be made “nullable” by adding a question mark ? to the end of it.
Non-nullable types can be passed the nullable ones, but the opposite is not true.
| SillyScript | JSON |
|---|---|
|
SillyScript code:
|
The equivalent JSON:
|
List
A list of data entries. A mixed list is denoted with just list.
A list that only contains a single type can be denoted using TYPE list (for example: int list).
| SillyScript | JSON |
|---|---|
|
SillyScript code:
|
The equivalent JSON:
|
Dictionary
An unordered list of data entries with a unique identifier for each entry. A mixed dict is denoted with just dict.
A dictionary that only contains a single type can be denoted using TYPE dict. For example: string dict.
Roles
A “role” can be given to a type as a piece of metadata. This is done using an exclamation point !.
def Something(input: dict!funny) -> dict!sad:
count: input.number
A type with a role can only be passed to another type with the same role identifier.
# Error: dict!sad cannot be passed to dict!funny.
Something(Something({ number: 32 }));
Custom Syntax
SillyScript is about being silly; what’s more silly than programming your programming language in your programming language? How certain statements should be generated for each project may be different, so it’s up to the user to describe which statements are supported and how they are generated.
The syntax keyword can be used to create custom syntax. The structure of a custom syntax declaration looks like this:
syntax NAME:
pattern:
PATTERN
| Input | Description |
|---|---|
NAME |
A globally unique name for your syntax declaration. |
PATTERN |
The syntax template this declaration adds. |
Here is an example of a very basic custom syntax.
| SillyScript | JSON |
|---|---|
|
The SillyScript custom syntax:
|
The equivalent JSON:
|
Expression Inputs
The above syntax doesn’t take any expression inputs, so it simply generates an empty object.
To accept expressions within the custom syntax, an argument surrounded by triangle brackets may be used:
| SillyScript | JSON |
|---|---|
|
The SillyScript custom syntax:
|
The equivalent JSON:
|
Multiple Patterns
A single custom-syntax declaration may contain multiple patterns. Each pattern may have different expression inputs, but any expression inputs with the same names MUST also have the same types.
| SillyScript | JSON |
|---|---|
|
The SillyScript custom syntax:
|
The equivalent JSON:
|
If Example
Let’s try a more complicated example: an if statement.
syntax If:
pattern -> dict!action:
if <condition: dict!condition>:
<contents: dict!action list>
This could be used in this SillyScript like so:
| SillyScript | JSON |
|---|---|
|
|
Pattern Type
To specify the type a pattern returns using -> TYPE. This can be helpful for assigning roles to dicts returned by patterns.
This can be used to simulate custom operators:
syntax NumEquality:
pattern -> dict!condition:
<left_number: dict!num> == <right_number: dict!num>
Borrowing from the if syntax code above, one can do:
| SillyScript | JSON |
|---|---|
|
|
Else Example
Let’s say we want to allow for an “else” case in our “if” syntax. Let’s create a new syntax declaration. We need to add internal: true so this syntax isn’t available for use with normal code.
syntax Else:
pattern:
else:
<contents: dict!action list>
Now we can add an optional “else” case in our “if” syntax. The ? after the “else_contents” identifier means this syntax is optional. The “if” still works even if there isn’t an “else”.
syntax If:
pattern:
if <condition: dict!condition>:
<contents: dict!action list>
<else_contents?: syntax!Else>