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
absentandasbreakcallcheckcreatedoendfalsefunctioninitializenotnovaluenullorotherwisepleaserepeatreturnstructurethenthistrueundefinedvariablewhetherwhile
Conditional keywords
Conditional keywords can be used as identifiers
addargumentargumentsbydivdoesequalfieldfieldsfromgogreaterhashaveislessmodmulnoofoutparameterparametersreturnssetsleepsubtakethanthatthetovaluewith