Bali is designed to be reasonably simple to compile. The Bali language changes every semester.
We use the following notation throughout this document:
program | [declarations ] : (class | function)* | A program consists of zero or more declarations (global variables) followed by zero or more classes and/or functions. |
function | type name ( [declarations] ) : [ declarations ] : statement* end | A function has a return-type, a name, 0 or more parameters, and a body consisting of optional declarations (local variables) followed by zero or more statements. |
class | class name [ extends name ] : [ declarations ] : function* endclass | A class has a name and can inherit from at most one class. Its body consists of declarations (i.e., fields) followed by zero or more methods (each method looks like a function). |
declarations | type name ( , type name )* | Each declaration is a type followed by a name. |
type | ( int | boolean | char | float | void | name ) ( [ ] )* | There are predefined types (int, boolean, char, float, void) and user-defined types (i.e., classes). There are also corresponding array types. Note that void is is only valid as a return type and cannot be used within an array type. |
statement | reference = expression ; | An assignment statement. |
reference ; | Function call (useful for side-effects). | |
if expression then statement* [ else statement*] endif | An if-statement has an optional else part. | |
loop statement* ( while | until ) expression ; statement* endloop | Looping. Note that there are two blocks of statements. The loop works by executing the first block, then checking the condition and possibly exiting the loop, then executing the second block. If the condition causes a loop-exit then the second block is not executed. After executing the second block the loop starts over again with the first block. Either statement-block in a loop can be empty or both blocks be nonempty. | |
return [ expression ] ; | Return statement. The type of the expression must match the return-type of the function. The no-expression version is semantically valid within a constructor or if the function's return-type is void. | |
print expression ( , expression )* ; | Print statement. Multiple expressions can be printed. Ideally, all are printed on a single line with a space between adjacent items, but this isn't possible with SaM-code. | |
reference | ( name | this | super ) modifier* | A reference typically evaluates to a specific "location" appropriate for storage or retrieval. Modifiers are evaluated left-to-right. Keywords this and super are only valid within a class method; this represents the current instance; super represents the current instance treated as an instance of the (syntactic) super-class. If this is used as a function, it calls the constructor for this class. If super is used as a function it calls the constructor for the super class. |
modifier | subscript | functionArgs | fieldRef | The modifiers for a reference. |
subscript | [ expression ] | A subscript. |
functionArgs | ( [ expression ( , expression )* ] ) | Function arguments. |
fieldRef | . name | Field reference. |
expression | [ + | - | not ] term ( binaryOp term )* | An expression is a a sequence of terms separated by binary operators. There can be an optional sign or boolean-negation in front of the first term of an expression; it is applied to the first term. Operators are evaluated left-to-right (i.e., no precedence rules). |
binaryOp | arithmeticOp | comparisonOp | booleanOp | The three kinds of binary operators. |
arithmeticOp | + | - | * | / | % | Operators for arithmetic. |
comparisonOp | < | <= | == | != | > | >= | Comparison operators. |
booleanOp | and | or | Boolean operators (both are short-circuiting). |
term | literal | ( expression ) | arrayValue | inputValue | reference | A term is a literal, a parenthesized expression, an array value, an input value, or a reference. |
literal | integer | char | string | float | true | false | null | Unsigned integers (e.g., 123, 6, 44), single characters (e.g., 'a', 'A', 'x'), strings (e.g., "hello", "there"), unsigned floating-point numbers (e.g., 3.1415926, 6.02e+23, .25, 18.), boolean constants, and the no-object indicator. |
arrayValue | type arrayElementList | An array value consists of a type indicator (all elements of the array must be of this type) followed by a list of elements. |
arrayElementList | { [ arrayElement ( , arrayElement )* ] } | The elements of the array. |
arrayElement | expression | arrayElementList | An array value can contain an "untyped" array element list if it is a multidimensional array. |
inputValue | readInt | readChar | readLine | readFloat | These "values" are read from standard input; readInt expects an integer (initial blanks are ignored, an initial + or - is OK), readChar corresponds to the next input character, readLine brings in the next line as a string (a character array), and readFloat expects a floating point number (initial blanks are ignored, an initial + or - is OK, exponents are OK.) |
name | any token whose kind is 'w' (see the Scanner212 code). | Note that a keyword cannot be used as a name (because keywords are all kind 'K'). |
comments | Anything following a # on a line is considered to be a comment. This doesn't show up in the grammar above because it's handled by the scanner (Scanner212.java). |
keywords |
|
program |
|
main function |
|
declarations |
|
namespaces |
|
namespace rules for types |
|
functions |
|
parameters |
|
statements |
|
assignment statements |
|
expressions |
|
arrays |
|
multidimensional arrays |
|
input |
|
predefined names |
|
classes |
|
constructors |
|
this |
|
super |
|
upcasting |
|
downcasting |
|