Cooperscript is a Python dialect in which all operators precede their operands, and parentheses are used for all grouping (except string literals, which are delimited with double quotes). Cooperscript source files have a .COOP extension. Coopertags files which are used by Cooprnet have a .CPTG extension. COOPERScript stands for Compact Object-Oriented Program Editor and Runtime System. The first sylllable, coop, looks a bit like OO enclosed in parentheses. For old Cooperscript project, please follow above Android link.
Special Characters
- () grouping
- - used in identifiers
- ; end of stmt.
- : dot operator
- " string delimiter
- \ escape char.
- # comment
- Extra:
- _ used in identifiers
- $ string prefix char.
- * public switch
- {} block comment
Differences from Python
- Parentheses, not whitespace
- Operators come before their operands
- Information hiding (public/private)
- Single, not multiple inheritance
- Adds interfaces ("scool" defs.)
- Drops iterators and generators
- Adds lambdas
- Adds quote and list-compile functions, treating code as data
- Adds cons, car and cdr functionality
Version 0.1
- No inheritance
- No interfaces
- No IDE
Keyboard Aid
This optional feature enables hyphens, open parentheses, and close parentheses to be entered by typing semicolons, commas, and periods, respectively. When enabled, keyboard aid can be temporarily suppressed by using the Ctrl key in conjunction with typing semicolons, commas, and periods (no character substitution takes place). By convention, hyphens are used to separate words in multi-word identifiers, but semicolons are easier to type than hyphens. Similarly, commas and periods are easier to type than parentheses. Typing semicolon converts previous hyphen to a semicolon, and previous semicolon to a hyphen (use the Ctrl key to override this behaviour). Typing semicolon after close parenthesis simply inserts semicolon. The close delim switch automatically inserts a closing parenthesis/double quote when the open delimiter is inserted.
Grammar Notation
- Non-terminal symbol: <symbol>
- Optional text in brackets: [ text ]
- Repeats zero or more times: [ text ]...
- Repeats one or more times: <symbol>...
- Pipe separates alternatives: opt1 | opt2
- Comments in italics
Language Grammar
White space occurs between tokens (parentheses and semicolons need no adjacent white space, also any semicolon before a close parenthesis may be omitted):
<source file>:
- [<use>] [ * <vars>] [<vars>] [ do <block>] [<def>]... [<class>]... [ do <block>]
<use>:
- use ( <import-semi>... )
<import-semi>:
- <import stmt> ;
<import stmt>:
- import <module>
- import ( <module>... )
- from <rel module> import <mod list>
- from <rel module> import all
<module>:
- <name>
- ( <name> as <name> )
- ( : <name>... [ as <name>] )
<mod list>:
- <id as>
- ( <id as>... )
<id as>:
- <mod id>
- ( <mod id> as <name> )
<mod id>:
- <mod name>
- <class name>
- <func name>
- <var name>
<rel module>:
- ( : [<num>][<name>]... )
- <name> // ?
<class>:
- ( [ * ] <cls typ><name> [<base class>][<does>] [ * <vars>] [<vars>] <def>... )
- ( [ * ] scool <name> [<does>] [<const list>] [<def hdr>]... )
- ( [ * ] enum <name><elist> )
<cls typ>:
- class
- abclass
<does>:
- does ( <scool name>... )
<scool name>:
<base class>:
- <name>
- ( : <name><name>... )
<const list>:
- const ( <const pair>... )
<const pair>:
- ( <name><const expr> )
<def hdr>:
- ( <defun><name> ( [<parms>] ) [<dec>] )
<def>:
- ( [ * ] <defun><name> ( [<parms>] ) [<vars>] [<dec>] do <block> )
<defun>:
- def
- abdef
<vars>:
- var ( <id>... )
<parms>:
- <parm>... [ ( * <id> ) ] [ ( ** <id> ) ]
<parm>:
- <id>
- ( tuple <id>... )
- ( <set op><id><expr> )
- ( <set op> ( tuple <id>... ) <expr> )
<dec>:
- decor <call expr>...
<block>:
- ( [<stmt-semi>]... )
<stmt-semi>:
- <stmt> ;
<jump stmt>:
- <continue stmt>
- <break stmt>
- <return stmt>
<pjump stmt>:
- return <expr>
- ** <raise stmt>
<raise stmt>:
- raise [<expr> [ from <expr>]]
<stmt>:
- <open stmt>
- <closed stmt>
<open stmt>:
- <if stmt>
- <while stmt>
- <for stmt>
- ** <try stmt>
- <pjump stmt>
- <pcall stmt>
- <asst stmt>
- <del stmt>
<closed stmt>:
- <jump stmt>
- <call stmt>
- <print stmt>
<call expr>:
- ( <name> [<arg list>] )
- ( : <obj expr> [<colon expr>]... ( <method name> [<arg list>] ))
- ( call <expr> [<arg list>] )
<call stmt>:
- ( <name> [<arg list>] )
<pcall stmt>:
- : <obj expr> [<colon expr>]... ( <method name> [<arg list>] )
- call <expr> [<arg list>]
<colon expr>:
- <name>
- ( <name> [<arg list>] )
<arg list>:
- [<expr>]... [ ( <set op><id><expr> ) ]...
<asst stmt>:
- <asst op><target expr><expr>
- <set op> ( tuple <target expr>... ) <expr>
<asst op>:
- set | addset | minusset | mpyset | divset |
- idivset | modset |
- shlset | shrset | shruset |
- andbset | xorbset | orbset
- andset | xorset | orset
- = | += | -= | *= | /= |
- //= | %= |
- <<= | >>= | >>>= |
- &= | ^= | '|=' |
- &&= | ^^= | '||='
<set op>:
- set | =
<target expr>:
- <name>
- ( : <name> [<colon expr>]... <name> )
- ( slice <arr><expr> [<expr>] )
- ( slice <arr><expr> all )
- ( <crop><cons expr> )
<arr>: string or array/lyst
- <name>
- <expr>
<if stmt>:
- if <expr> do <block> [ elif <expr> do <block>]... [ else <block>]
<while stmt>:
- while <expr> do <block>
- do <block> while <expr>
<for stmt>:
- for <name> in <expr> do <block>
<try stmt>:
- try <block> <except clause>... [ else <block>] [ finally <block>]
- try <block> finally <block>
<except clause>:
- except <name> [ as <name>] do <block>
<return stmt>:
- return
<break stmt>:
- break
<continue stmt>:
- continue
<del stmt>:
- del <expr>
<paren stmt>:
- ( <open stmt> )
- <closed stmt>
<qblock>:
- ( quote [<paren stmt>]... )
<expr>:
- <keyword const>
- <literal>
- <name>
- ( <unary op><expr> )
- ( <bin op><expr><expr> )
- ( <multi op><expr><expr>... )
- ( <quest><expr><expr><expr> )
- <lambda>
- ( quote <expr>... )
- <renum expr>
- <cons expr>
- <tuple expr>
- <lyst expr>
- <dict expr>
- <bitarray expr>
- <string expr>
- <bytezero expr>
- <bytes expr>
- <target expr>
- <obj expr>
- <cast>
<quest>:
- quest | ?
<obj expr>:
- <name>
- <call stmt>
<unary op>:
- minus | notbitz | not |
- - | ~ | !
<bin op>:
- <arith op>
- <comparison op>
- <shift op>
- <bitwise op>
- <boolean op>
<arith op>:
- div | idiv | mod | mpy | add | minus |
- / | // | % | * | + | -
<comparison op>:
- ge | le | gt | lt | eq | ne | is | in |
- >= | <= | > | < | == | !=
<shift op>:
- shl | shr | shru |
- << | >> | >>>
Note: some operators delimited with single quotes for clarity (quotes omitted in source code)
<bitwise op>:
- andbitz | xorbitz | orbitz |
- & | ^ | '|'
<boolean op>:
- and | xor | or |
- && | ^^ | '||'
<multi op>:
- mpy | add | strdo | strcat |
- and | xor | andbitz | xorbitz |
- or | orbitz |
- * | + | % | + |
- && | ^^ | & | ^ |
- '||' | '|'
<const expr>:
- <literal>
- <keyword const>
<literal>:
- <num lit>
- <str lit>
- <bytes lit>
<cons expr>:
- ( cons <expr> [<expr>] )
- ( <crop><cons expr> )
<tuple expr>:
- ( tuple <expr>... )
<lyst expr>:
- ( lyst [<expr>]... )
<dict expr>:
- ( dict [ <pair>]... )
<bitarray expr>:
- ( bitarray <enum name> [<elist>] )
- ( bitarray <enum name><idpair>... )
<elist>:
- <id>...
- <intpair>...
- <chpair>...
<intpair>: // integer constant
- <int const>
- ( <int const><int const> )
<chpair>: // one-char. string
- <char lit>
- ( <char lit><char lit> )
<idpair>:
- <id>
- ( <id><id> )
<pair>: // expr1 is a string
- ( <expr1><expr2> )
- ( <str lit><expr> )
<renum expr>:
- ( renumize <expr><ren id>... )
- ( renumize <expr><ren int>... )
- ( renumize <expr><ren ch>... )
<ren id>:
- ( 0 <id> )
- ( 1 <id> )
- ( 1 <id><id> )
<ren int>: // expr is <dec int>
<ren ch>: // expr is <char lit>
- ( 0 <expr> )
- ( 0 <expr><expr> )
- ( 1 <expr> )
- ( 1 <expr><expr> )
<cast>:
- ( cast <type><expr> )
<print stmt>: // built-in function
- ( print <expr>... )
- ( println [<expr>]... )
- ( echo <expr>... )
<lambda>: // must pass qblock thru compile func
- ( lambda ( [<id>]... ) <expr> )
- ( lambda ( [<id>]... ) do <block> )
- ( lambdaq ( [<id>]... ) do <qblock> )
No white space allowed between tokens, for rest of Cooperscript Grammar:
<white space>:
- <white token>...
<white token>:
- <white char>
- <line-comment>
- <blk-comment>
<line-comment>:
- # [<char>]... <new-line>
<blk-comment>:
- { [<char>]... }
<white char>:
- <space> | <tab> | <new-line>
<name>:
- [<underscore>]... <letter> [<alnum>]... [<hyphen-alnum>]... [<underscore>]...
<hyphen-alnum>:
- <hyphen><alnum>...
<alnum>:
- <letter>
- <digit>
In plain English, names begin and end with zero or more underscores. In between is a letter followed by zero or more alphanumeric characters. Names may also contain hyphens, where each hyphen is preceded and succeeded by an alphanumeric character.
<num lit>:
- <dec int>
- <long int>
- <oct int>
- <hex int>
- <bin int>
- <float>
<dec int>:
- [<hyphen>] 0
- [<hyphen>] <any digit except 0> [<digit>]...
<long int>:
- <dec int> L
<float>:
- <dec int> <fraction> [<exponent>]
- <dec int> <exponent>
<fraction>:
- <dot> [<digit>]...
<exponent>:
- <e> [<sign>] <digit>...
<e>:
- e | E
<sign>:
- + | -
<keyword const>:
- none
- true
- false
<oct int>:
- 0o <octal digit>...
<hex int>:
- 0x <hex digit>...
- 0X <hex digit>...
<bin int>:
- 0b <zero or one>...
- 0B <zero or one>...
<octal digit>:
- 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
<hex digit>:
- <digit>
- A | B | C | D | E | F
- a | b | c | d | e | f
<str lit>:
- [ $ <str prefix>] <quoted str>
<str prefix>:
- r | u | R | U
<quoted str>:
- " [<str item>]... "
<str item>:
- <str char>
- <escaped str char>
- <str newline>
<str char>:
- any source char. except "\", newline, or end quote
<str newline>:
- \ <newline> [<white space>] "
<bytes lit>:
- $ <byte prefix><quoted bytes>
<byte prefix>: any case/order
- b | br
<quoted bytes>:
- " [<bytes item>]... "
<bytes item>:
- <bytes char>
- <escaped char>
- <str newline>
<bytes char>:
- any ASCII char. except "\", newline, or end quote
<escaped char>:
- \\ backslash
- \" double quote
- \} close brace
- \a bell
- \b backspace
- \f formfeed
- \n new line
- \r carriage return
- \t tab
- \v vertical tab
- \ooo octal value = ooo
- \xhh hex value = hh
<escaped str char>:
- <escaped char>
- \N{name} Unicode char. = name
- \uxxxx hex value (16-bit) = xxxx
<crop>:
- c <crmid>... r
<crmid>:
- a | d