The Duck Programming Language official homepage
View the Project on GitHub teamduck/duck-lang
This project is maintained by
Greg Tourville
Hosted on GitHub Pages — Theme by orderedlist
A simple scripting language based on the idea of duck-typing (or dynamic typing).
“When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.” — James Whitcomb Riley
The duck programming language supports first-class functions, integer and floating-point arithmetic, string manipulation, dynamically-sized arrays, dictionary types, and basic object oriented programming. The syntax is strongly reminiscent of BASIC, Lua, or Python. While indentation is not strictly specified, the language does require specific whitespace in required newlines at the end of certain statements. Duck is currently only implemented in the form of a slow, interpreted frontend, making it useful strictly as a scripting language. This frontend has been developed entirely in C code.
The syntax of loops is somewhat different than in BASIC or other languages. For example, a while loop has the following syntax:
while condition do
// loop body
// ...
loop
while a for loop in Duck looks like this
for i = 1 to 10 do
// iterated instructions
// ...
// ...
loop
Notice the use of the syntax `do' and `loop.' There are a number of other example programs in the examples directory of the source repository.
The programming language's grammar is defined in deterministic context-free Backas-Naur form, viewable here. The duck language has its own parser-generator, generating SLR(1) parse tables, so it is relatively easy to change the syntax of the language. Other optional ways to configure the language include disabling case-sensitivity or changing the format of comments, which are currently implemented as /* C-style block comments */
, // full line comments
, ; semicolon until end of line comments
, and # any macro use
.
As an example of what a typical program might look like written in Duck, the following is an example of computing prime numbers.
function display_primes(limit)
count = 0
numbers = []
for i = 2 to limit do
numbers[i] = 1
loop
for i = 2 to limit do
if numbers[i] == 1 then
count = count + 1
for j = 2 to limit/i do
numbers[i*j] = 0
loop
duck.println(i)
end
loop
end
This is a virtual console running the Duck interpreter.
Click to Enable.
Additionally, there is a less interactive scratchpad for programming here and a larger version of this console app here although the recommended way to develop using duck is to download the runtime executable.
It is easy to port libraries to Duck. Function hooks are implemented as pointers, of the form int (function_pointer)(int)
where the argument count is passed as the only parameter. Arguments are bound as string identifiers, and are accessed dynamically in the bound-function's body.
Example:
void BindStandardLibrary()
{
VALUE duckStdLib = LinkNamespace("duck");
VALUE print = CreateFunction(DuckPrint);
AddParameter(print, "output");
LinkFunction(duckStdLib, "print", print);
LinkFunction(duckStdLib, "println", print);
VALUE prompt = CreateFunction(DuckPrompt);
LinkFunction(duckStdLib, "prompt", prompt);
}
Duck has a standard library supporting both command-line input and output. See: stdduck.h. There are also SDL and OpenGL bindings to support graphical windowed programming.
Here is a list of those functions:
Duck uses CMake 2.8. To build simply run:
> cmake .
> make
Building gduck with SDL support requires SDL and OpenGL libraries. There are no platform specific libraries.
; duck programming language
<program> ::= <stmt list>
<stmt list> ::= <stmt> <stmt list>
<stmt list> ::= <epsilon>
<stmt> ::= import <identifier> <endl>
<stmt> ::= <endl>
<stmt> ::= <expr> <endl>
<stmt> ::= <assignment> <endl>
<stmt> ::= <function def> <endl>
<stmt> ::= <if> <endl>
<stmt> ::= <for loop> <endl>
<stmt> ::= <while loop> <endl>
<stmt> ::= return <expr> <endl>
<stmt> ::= break <endl>
<stmt> ::= continue <endl>
<function def> ::= function <identifier> <parameters> <endl> <stmt list> end
<parameters> ::= <epsilon>
<parameters> ::= ( )
<parameters> ::= (<param decl>)
<param decl> ::= <identifier>
<param decl> ::= <param decl>, <identifier>
<if> ::= if <condition> then <endl> <stmt list> <else if>
<else if> ::= else <endl> <stmt list> end
<else if> ::= else <if>
<else if> ::= end
<for loop> ::= for <identifier> = <arithmetic> to <arithmetic> do <endl> <stmt list> loop
<while loop> ::= while <condition> do <endl> <stmt list> loop
<assignment> ::= <l-value> = <assignment>
<assignment> ::= <l-value> = <condition>
<l-value> ::= <identifier>
<l-value> ::= ( <l-value> )
<l-value> ::= <reference> . <identifier>
<l-value> ::= <reference> [ <expr> ]
<expr> ::= <condition>
<condition> ::= <condition> and <logic>
<condition> ::= <condition> or <logic>
<condition> ::= <logic>
<logic> ::= not <comparison>
<logic> ::= <comparison>
<comparison> ::= <comparison> == <arithmetic>
<comparison> ::= <comparison> != <arithmetic>
<comparison> ::= <comparison> \< <arithmetic>
<comparison> ::= <comparison> > <arithmetic>
<comparison> ::= <comparison> \<= <arithmetic>
<comparison> ::= <comparison> >= <arithmetic>
<comparison> ::= <arithmetic>
<arithmetic> ::= <arithmetic> + <term>
<arithmetic> ::= <arithmetic> - <term>
<arithmetic> ::= <term>
<term> ::= <term> * <factor>
<term> ::= <term> / <factor>
<term> ::= <factor>
<factor> ::= -<factor>
<factor> ::= !<factor>
<factor> ::= <final>
<final> ::= ( <expr> )
<final> ::= <boolean>
<final> ::= <integer>
<final> ::= <float>
<final> ::= <string>
<final> ::= <object>
<final> ::= <reference>
<reference> ::= <l-value>
<reference> ::= <reference> ( )
<reference> ::= <reference> ( <arguments> )
<arguments> ::= <arguments>, <expr>
<arguments> ::= <expr>
<object> ::= [ ]
<object> ::= [ <array init> ]
<object> ::= [ <dictionary init> ]
<array init> ::= <array init>, <expr>
<array init> ::= <expr>
<dictionary init> ::= <dictionary init>, <identifier> : <expr>
<dictionary init> ::= <identifier> : <expr>
<boolean> ::= true
<boolean> ::= false
Greg Tourville - Team Duck
Hiroyuki Sano
Robert Cope