Siteswap Query Language
By using the Siteswap Query Language (SsQL), you can specify the search method and the display method of results in detail. The complete syntax is:
FROM "pattern" LET variable-definition WHERE acquisition-condition SELECT display-items ORDER BY sort-condition LIMIT number
However, you can omit everything except the FROM clause. Specify the clauses that are not omitted in this order. The LET clause can be specified multiple times.
In the FROM clause, describe the search pattern with double quotation marks. If you want to use double quotation marks in your pattern, you must escape them with \.
Only the maximum number can be specified in the LIMIT clause. The time limit can not be specified, so if you want to stop the search halfway, press the stop button. If you omit the LIMIT clause, the search continues indefinitely.
Acquisition condition
Specify the acquisition condition by combining variables, properties, methods, and operators in the WHERE clause. For example:
WHERE $0.balls == 3
If the condition is satisfied, the string is acquired, and if not, it is not acquired. If you omit the WHERE clause, you get all the generated strings.
Variables include auto-defined variables and user-defined variables. Auto-defined variables are specified by $ + numbers such as $0, $1, $2, .... User-defined variables will be described later. $0 represents the entire string, and $1, $2, etc. represent the first group, second group, and so on. You can write $ instead of $0 as an abbreviation. If the pattern specified in the FROM clause is (5+)([13]), the string are assigned to the variable as follows.
$0 | $1 | $2 | |
---|---|---|---|
1st | 51 | 5 | 1 |
2nd | 53 | 5 | 3 |
3rd | 551 | 55 | 1 |
4th | 553 | 55 | 3 |
5th | 5551 | 555 | 1 |
: | : | : | : |
Properties are specified after variable and dot.
property | explanation | example |
---|---|---|
pattern | the string itself | 315315 |
length | string length | 6 |
sum | sum of heights | 18 |
reverse | reverse order | 513513 |
min | minimum pattern | 153153 |
max | maximum pattern | 531531 |
omission | abbreviation | 315 |
standard | standard form | 531 |
jugglable | whether jugglable | 1 |
valid | whether valid siteswap | 1 |
balls | number of balls | 3 |
period | siteswap period | 3 |
state | siteswap state | 19 |
int10 | base 10 value | 315315 |
int36 | base 36 value | 183315353 |
The value of "jugglable" is 1 if it is jugglable and 0 otherwise. "valid" is similar. "balls" and "state" will be -1 if the pattern is not jugglable. "period" will be -1 if the pattern is not a siteswap, even if it is jugglable. "int10" is a numerical value from the beginning to the position where it can be regarded as a decimal integer. "int36" is similar. Property can be omitted. If omitted, it is assumed that "pattern" is specified.
Methods are specified in the same way as properties, but with parentheses followed by arguments, such as $0.at(1). In the example in the following table, methods are applied to string "12345".
method | explanation | n = 1 | n = -2 |
---|---|---|---|
at(n) | character at that index | 2 | 4 |
rotate(n) | rotation for n characters | 23451 | 45123 |
skip(n) | skip n characters | 2345 | 123 |
take(n) | take n characters | 1 | 45 |
All of these methods count from the left if you specify 0 or a positive number as an argument, and from the right if you specify a negative number. The leftmost position is 0 and the rightmost position is -1.
Some methods are iterative methods that take a lambda expression as an argument.
iterator | explanation |
---|---|
every(lambda) | whether it holds for all indexes |
some(lambda) | whether it holds for any one index |
Lambda expressions are specified in the following format:
index => condition
or
index, whole => condition
Here, both the index variable and the variable that represents the whole are user-defined variables. User-defined variables can be specified as $ + strings, such as $index, $x1, $_, and can be used in acquisition conditions. The following is a concrete example of the former format.
$0.every($index => $0.at($index) == 1)
If the length of $0 is n, 0 to n-1 are assigned to $index in order, and the right side of => is iterated. On the right side, it is determined whether the characters from the 0th digit to the n-1th digit are 1, so throughout this example, it is determined whether all the digits of $0 are 1.
$0.take(2).some($index, $whole => $whole.at($index) == 1)
This is a concrete example of the latter form, which determines if there is a 1 in the first two digits of $0. It is the same as writing $0.take(2) instead of $whole, but more concise.
The following is a list of operators by priority.
priority | operator | meaning |
---|---|---|
1 | . | string on the right is a property or a method |
2 | * | multiplication |
/ | quotient of integer division | |
% | remainder of integer division | |
3 | + | addition |
- | subtraction | |
& | concatenation of strings | |
4 | == | left and right values are equal |
!= | left and right values are different | |
<> | ||
< | left value is less than right value | |
<= | left value is less than or equal to right value | |
> | left value is more than right value | |
>= | left value is more than or equal to right value | |
IN(...) | left value is contained in ... | |
NOT IN(...) | left value is not contained in ... | |
5 | NOT | right condition is false |
6 | AND | both left and right conditions are true |
7 | OR | either left or right condition is true |
If operators with the same priority are listed, they are evaluated from the left. When you want to change the priority, enclose the part in parentheses, such as 2*(3+4).
Only decimal integers are treated as numbers. When performing numerical calculation on a string, it is assumed that the "int10" property is implicitly specified. The result of the comparison operation is 1 for true and 0 for false. In the operation of NOT, AND and OR, only the number 0, the string "0", and the empty string represent false, and true otherwise.
The IN operator is used as follows:
$0.standard IN("71", "62", "53")
In this case, it will be true (or 1) if the standard form of the variable $0 is 71, 62, or 53.
Display items
Specify display items such as variables and constants separated by white space in the SELECT clause. For example:
SELECT $0 "(" $0.balls ")"
White spaces are not included in the displayed string, so specify the spaces in double quotation marks if necessary. The string enclosed in double quotation marks is output as is. If you omit the SELECT clause, you get the entire generated string (assuming $0.pattern was specified).
You can also use operators. For example:
SELECT $0.int10 "+1=" $0.int10 + 1
genarates 3+1=4 etc.
To suppress the output of the same string, specify DISTINCT after SELECT. If you want to generate only unique strings, describe as follows.
SELECT DISTINCT $0
DISTINCT is similar to the WHERE clause in that it limits the number of strings displayed, but WHERE covers the conditions that the generated string satisfies, whereas DISTINCT only covers whether the entire string processed by SELECT already exists.
Sort condition
Specify sorting conditions separated by commas in the ORDER BY clause.
ORDER BY $0.period DESC, $0
If you specify DESC after the condition, the order will be descending. If you specify ASC or nothing, the order will be ascending. The above example means "descending by siteswap period, then ascending by string itself". If the strings generated are 3, 441, 531, then the longer siteswap periods 441 and 531 come first and the shorter period 3 comes later. In 441 and 531, 441 is smaller as a string, so it comes earlier, and finally 441 531 3 is output.
If you omit the ORDER BY clause, they are displayed in the order they were generated.
Variable definition
The LET clause defines a variable that can be used throughout the statement.
LET $const = "123"
The left side of equal is the variable name, and the right side is the definition. Like user-defined variables that appear in lambda expressions, variable names are specified with the $ + string. The first character of the variable name can be an alphabet or an underscore, and numbers can be used in addition to that after the second character. Case is ignored and $name and $Name and $NAME are treated as the same name. You can not define multiple variables with the same name.
Any number of LET clauses can be written for one SsQL statement. You can use variables as well as constants in definitions.
LET $var1 = $1 LET $var2 = $var1 + 3 LET $var3 = $0.at($index)
Using an undefined variable will result in an error, but the order of definition does not matter, so there is no problem if you use $var3 as follows.
WHERE $0.every($index => $var3 < 3)
Comments and other
You can also write a comment in SsQL.
-- 1 line comment /* Multi- line comment */
Line comments are from -- to the end of the line, block comments are from /* to */. Only one line comment can be specified per line, and it can not span multiple lines. On the other hand, a block comment can be written over multiple lines, or multiple block comments can be written in the middle of a line. However, you can not nest comments.
You can write SsQL in free format. That is spaces, line breaks, and comments between keywords are ignored.
Uppercase letters are converted to lowercase. The message when there is an error is also displayed as a string converted to lowercase letters.
Language specifications
For reference, I describe the specifications of the accepted SsQL in HABA format.
Query ::= From Let* Where? Select? Order? Limit? ; From ::= 'FROM' String ; String ::= """(\\""|[^""])*""" ; Let ::= 'LET' User '=' Term ; Where ::= 'WHERE' Condition ; Condition ::= Part ('OR' Part)* ; Part ::= Unit ('AND' Unit)* ; Unit ::= 'NOT'? Expression ; Expression ::= Term (Compare Term | Clause)? ; Term ::= Factor (('+' | '-' | '&') Factor)* ; Factor ::= Value (('*' | '/' | '%') Value)* ; Value ::= Element ('.' (Property | Method | Iterator))* ; Element ::= Auto | User | Literal | '(' Condition ')' ; Auto ::= "\$[0-9]*" ; User ::= "\$[a-z_][a-z_0-9]*" ; Literal ::= String | Integer ; Integer ::= "[0-9]+" ; Property ::= 'pattern' | 'length' | 'sum' | 'reverse' | 'min' | 'max' | 'omission' | 'standard' | 'jugglable' | 'valid' | 'balls' | 'period' | 'state' | 'int10' | 'int36' ; Method ::= ('at' | 'rotate' | 'skip' | 'take') '(' Parameter ')' ; Parameter ::= Term | '-' Value ; Iterator ::= ('every' | 'some') '(' Lambda ')' ; Lambda ::= User (',' User)? '=>' Condition ; Compare ::= '==' | '!=' | '<>' | '<' | '<=' | '>' | '>=' ; Clause ::= 'NOT'? 'IN' '(' List ')' ; List ::= Literal (',' Literal)* ; Select ::= 'SELECT' 'DISTINCT'? View ; View ::= Term+ ; Order ::= 'ORDER' 'BY' Multiple ; Multiple ::= Single (',' Single)* ; Single ::= Value ('ASC' | 'DESC')? ; Limit ::= 'LIMIT' Term ; Space ::= "\s+" ; Line ::= "--[^\n]*(\n|$)" ; Block ::= "/\*((?!\*/)[\s\S])*\*/" ;