Syntax
VFPL has a deliberately verbose syntax, to provide the maximal explicitness and reduce accidental mistakes
Every statement in VFPL starts with a please
and ends with a dot .
.
Variables are declared and initialized the following way:
please initialize variable x as Integer with the value of 3.
They can be reassigned using a set
statement
please set the variable X to the value of 6
Here we use uppercase for the variable name, which, according to convention, suggests a mutable variable.
Loops are done using while loops
please repeat while True do
please end while.
Conditionals are done using check
and otherwise
please check whether True, then do
please end check.
please check whether False, then do
otherwise,
please end check
You can write comments using the HTML syntax
<!-- Hi, this is a comment -->
Functions can be created like this
please create function hello_world with no parameters that returns absent
<!-- ... -->
please return absent from the function.
please end function hello_world.
please create function print_int with the parameter x as Integer that returns null
<!-- ... -->
please return null from the function.
please end function print_int.
please create function add_ints with the parameters x as Integer and y as Integer that returns Integer
please return (add x to y) from the function.
please end function add_ints.
please create function add_3_ints with the parameters x as Integer, y as Integer and z as Integer that returns Integer
please return (add x to (add y to z)) from the function.
please end function add_3_ints.
And then called using similar syntax, where the parameter names have to be specified in the correct order
please call hello_world with no arguments.
please call print_int with the argument 5 as x.
please call add_ints with the arguments 5 as x and 6 as y.
please call add_3_ints with the arguments 5 as x, 6 as y and 7 as z.
Grammar
The grammar is written in BNF
// VFPL Grammar
////// Base rules
program ::= body
body ::= (statement)*
////// Other rules
typed-ident ::= ident "as" type
value-ident ::= expr "as" ident
ident ::="regexp:\w"+
// type
type ::= ident | nullable
nullable ::= "absent" | "null" | "novalue" | "undefined"
////// Item rules
// function
fn-decl ::= "create function" ident "with" fn-params fn-return
body
"please end function" ident
fn-params ::= fn-no-params | fn-single-params | fn-multi-params
fn-no-params ::= "no parameters"
fn-single-params ::="the parameter" typed-ident
fn-multi-params ::="the parameters" typed-ident ("," typed-ident)* "and" typed-ident
fn-return ::="that returns" type
// structure
struct-def ::= "define structure" ident "with" struct-fields? "please end define"
struct-fields ::= struct-field (("," struct-field)* "and" struct-field)?
struct-field ::= "the field" typed-ident
////// Statement rules
statement ::= "please" (
fn-decl |
struct-def |
variable-init |
variable-set |
if |
while |
break |
return |
terminate |
expr
) "."
variable-init ::= "initialize variable" typed-ident "with the value of" expr
variable-set ::= "set the variable" ident "to the value of" expr
// control flow
if ::= if-part "please end check"
if-part ::= "check wheter" expr ", then do" body (else)?
else ::= "otherwise, " (if-part | body)
while ::= "repeat while" expr "do"
body
"please end while"
break ::= "break out of this while"
return ::="return" expr "from the function"
terminate ::= "go to sleep"
////// Expression rules
expr ::= comparison
comparison ::= term ((
"does not have the value" |
"has the value" |
"is greater than" |
"is less than" |
"is greater or equal than" |
"is less or equal than"
) comparison)?
term ::= add | subtract | factor
add ::= "add" factor "to" term
subtract ::= "subtract" factor "from" term
factor::= multiply | divide | modulo | call-expr
multiply ::= "multiply" call-expr "with" factor
divide ::= "divide" call-expr "by" factor
modulo ::= "take" call-expr "modulo" factor
call-expr ::= call | primary-expr
primary-expr ::= "(" expr ")" | literal
// function call
call ::= "call" ident "with" call-args
call-args ::= call-no-arg | call-single-arg | call-multi-arg
call-no-arg ::="no arguments"
call-single-arg ::="the argument" value-ident
call-multi-arg ::="the arguments" value-ident ("," value-ident)* "and" value-ident
// literals
literal ::= struct-literal |nullable | "regexp:\".*\"" | number | "true" | "false" | ident
number ::= int | float
float ::= "-"? "regexp:\d"+ "."? "regexp:\d"+
int ::= "-"? "regexp:\d"+
// struct literal
struct-literal ::= ident "with" struct-lit-fields
struct-lit-fields ::= struct-lit-no-fields | struct-lit-fields-some
struct-lit-no-fields ::= "no fields"
struct-lit-fields-some::= value-ident (("," value-ident)* "and" value-ident)?
List of keywords
Normal keywords
Normal keywords cannot be used as identifiers
absent
and
as
break
call
check
create
do
end
false
function
initialize
not
novalue
null
or
otherwise
please
repeat
return
structure
then
this
true
undefined
variable
whether
while
Conditional keywords
Conditional keywords can be used as identifiers
add
argument
arguments
by
div
does
equal
field
fields
from
go
greater
has
have
is
less
mod
mul
no
of
out
parameter
parameters
returns
set
sleep
sub
take
than
that
the
to
value
with