Bali Specifications

CS 212 - Spring 2004

As discussed in lecture, we can specify a language in terms of its syntax (structural rules) and semantics (meaning). Although formal description methods exist for both kinds of specifications, we only formalize the Bali syntax. Bali's semantics are informally defined using English-language descriptions.

We use the following notation throughout this document:

Bali Syntax

Functions, Classes, and Methods
program  ->   (function | class)* There must be a 
main function
(see below)
function -> functionHeader functionBody
functionHeader -> ( type | void ) name ( [ parameters ] )
functionBody -> { variableDeclaration*
{
statement* }
Variable declarations
come before statements;
both are surrounded by
braces
type -> ( int | float | char | boolean | string | name ) ( [ ] )*
parameters -> type name (, type name )* Parameters are
separated by commas
variableDeclaration -> type name ( , name )* ;
class -> class name [ ( name )
{
fieldDeclaration* }  
{
constructor* }
{
method* }
Single-inheritance; 
field declarations come 
before constructors which 
come before methods
fieldDeclaration -> modifier variableDeclaration
constructor -> modifier name ( [ parameters ] ) functionBody
method -> modifier function
modifier -> public | private

Statements
statement ->   return [ expression ] ;
statement -> { statement* }
statement -> if expression then statement 
[ else statement ]
statement -> while expression do statement
statement -> do statement while expression ;
statement -> expression ;
statement -> print expression ; Output
statement ->  ; Empty statement
statement -> target = expression ;
target -> name [ subscript | . name ]

Expressions
expression ->   expPart [ binaryOp expPart ] Single operator (no 
precedence necessary)
expression -> [ [ expressionList ] ] An entire array
expPart -> unaryOp expPart
expPart -> literal
expPart -> ( expression ) Parenthesized expression
expPart -> name [ functionArgs | subscript | attributeRef ] Variable, function, 
subscripted variable, 
or object use
(field or method-call)
functionArgs -> ( [ expressionList ] ) Function arguments
expressionList -> expression ( , expression )*
subscript -> [ expression ] Array subscript
attributeRef ->  . name [ functionArgs ] Field or method-call
literal -> integer | character | float
string
| true | false | null
The various kinds 
of literals
binaryOp -> arithmeticOp | comparisionOp | booleanOp
arithmeticOp -> + | - | * /  | % % is mod (as in Java)
comparisonOp -> < | > | <= | >= | == | !=
booleanOp -> && |  | |  | ^ And (short circuiting),
or (short circuiting),
and xor
unaryOp ->  - | ! Unary minus, not

Tokens
name -> ( a-z | A-Z | _ ) ( a-z | A-Z | _ | 0-9 )*
Names are case sensitive.
integer -> Legal Java integers
character -> Single quotes around any printing 
ASCII character (e.g., 'a', '$', ' '); 
there is one special character: 
'\n' for newline 
float -> Numbers with a single decimal point
and no exponential part (e.g., 1.0, .05, 6.)
string -> Double quotes around any sequence
 of characters (that does not contain 
double quotes); there is one special 
character: "\n" for newline

Comments
  • Double slash // indicates that the remainder of the current line is a comment.
  • There are no multi-line comments.

Bali Semantics

program
  • All functions and classes of a program must be in the same file.
  • Like Java, Bali relies on automatic garbage collection.
  • Running a program means that the program's main function is executed.
mainFunction
  • There must be a function called main that has an empty parameter list. It is a semantic error if this function does not exist.
  • The return type for the main function must be int.
  • This integer value appears as the exit code when the SaM Simulator halts.
function
  • The type of the expression in the return statement must match the type specified in the function header.
  • If you "fall off the end" of the function body (i.e., you execute the last statement and that statement is not a return statement) then a default return is automatically executed.  If appropriate, this default-return returns a value using the same default rules as for a variable declaration (i.e., 0 for int, false for boolean, ' ' (space character) for char, 0.0 for float, and null for an object reference).
  • Functions can be overloaded if the parameters specified in the function header differ by type or by number of parameters or by order of parameter types.  Overloaded functions with the same function name must all have the same return type.
  • The declared type (i.e., the type that can be determined from declarations within the program) for an argument of a function, constructor, or method call must match the corresponding parameter type exactly.
  • Functions cannot be assigned to variables since there is no type that can be used to declare such a variable. 
parameters
  • Parameters pass by value.
  • Parameters are local to the current scope (either a function, a constructor, or a method).
variableDeclaration
  • Variables have default values : 0 for int, false for boolean, ' ' (space character) for char, 0.0 for float, and null for an object reference (or for a string or for an array)..
  • Variables must be declared before use.
  • Variables are local to the current scope (either a function, a constructor, or a method).
class
  • Fields, constructors, and methods are all local to the class's scope; they are accessible, using their unqualified names, from within constructors and methods in the same scope.
  • A class C inherits from at most one class (say B). B is called the super class of C. C is called a subclass of B.
  • A class C inherits all the public fields and methods of its super class (and of the super class's super class, etc.).
  • A method specified in some class C is said to override an inherited method that has the same signature. A signature consists of a method's name and its parameter types, in order. It is an error of these methods have different return types or if the overriding method is private.
  • A field specified in some class C is said to override an inherited field that has the same name.  It is an error if the overriding field is private. (For Bali, fields and methods follow essentially the same rules. This is not the case for Java where fields are shadowed rather than overridden.)
fieldDeclaration
  • Fields have default values (see variableDeclaration).
  • Fields are local to the current class.
modifier
  • Fields, constructors, and methods all have a modifier, either public or private.  A private item is accessible only from within its class.  A public item is accessible from anywhere.
constructor
  • A constructor has the same name as its class.
  • Constructors can be overloaded (see function).
  • If no constructor is provided, an empty, default constructor (with no parameters) is used.
  • Any call to the constructor of the super class must be done explicitly using a call to super(arguments). (This is different from Java where an implicit call to the no-argument constructor of the super class is made whenever no explicit call is present.)
method
  • See function.
this
  • As in Java, this refers to the current class instance.  It is only valid within a constructor or a method.
super
  • As in Java, super refers to the current class instance treated as if it were an instance of the super class.  It is only valid within a constructor or a method.
  • The form super(arguments) has special meaning when used within a constructor (see constructor).  It is only valid within a constructor. 
statement
  • Expressions in if, while, and do-while statements must be of type boolean.
  • For assignment statements, the types of the left-hand and right-hand sides must match.
  • The syntax allows the following problematic construct.
    if expression then if expression then statement else statement
    The else should be matched with the closest if.  This rule could have been incorporated into the syntax, but it would have made the syntax more complicated.
  • Rudimentary output is available via the print statement.
expression
  • For all binary operators, the operands must be of the same type.
    • For logical operators (&&, | |, ^, !), operands must be of type boolean.
    • For arithmetic operators (+, -, *, /), operands must be of type int or of type float.  Division (/) is integer division when operands are of type int.
    • For the mod operator (%), operands must be of type int.
    • For the relational operators (<, <=, >, >=), operands must be of type int, char, or float.
    • The equality (==) and inequality (!=) operators both work with all types of values.  Two class instances are equal if and only if they are both the same object.
    • Bali does not support division by zero, NaN, or infinity.
  • Limited type casting is available. 
    • An expression of the form item.className is of type classNameItem's declared type (i.e., the type that can be determined from declarations within the program) must be className or an ancestor or descendent of  classNameItem's actual type (i.e., the type of the specific instance that exists at runtime) must be className or a descendent of className.
arrays
  • When an array is declared, its initial value is null.
  • A list of elements enclosed in brackets (see expression, above) represents an entire array.  All the elements must have the same type. The resulting value is of type type[ ], where type is the type of the elements. Null elements are allowed for an array of objects, but there must be at least one element with a type (otherwise the array's type could not be determined).
  • The expression type[size] creates an array of the given size. Each element of the array is set to the appropriate default value (see variableDeclaration, above).
predefined functions
  • Rudimentary input is available via the read functions readInt( ), readChar( ), readFloat( ), and readString( ).  They each return a value of the indicated type.