Bali Specifications for Part 4

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 | boolean | name) [ [ ] ] Integer, boolean, class-type,
integer array, boolean array,
or class-type array
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 Constructor name must
match the class name
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 ] Can assign to a variable
or an array element
or a field

Expressions
expression ->   expPart [ binaryOp expPart ] Single operator (no 
precedence necessary)
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 | 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

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 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, 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 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 function scope.
variableDeclaration
  • Variables have default values : 0 for int, false for boolean, and null for an object reference (a class-type or an array).
  • Variables must be declared before use.
  • Variables are local to the current function scope.
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 public 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.
  • It is illegal for a field of some class C to have the same name as a public field in the superclass of C. (This is different from Java where fields can be shadowed.)
  • It is OK for a field and a method to share the same name (as in Java).
  • A class's super class must be defined before the class.
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.
  • There is no new keyword as in Java; instead, a constructor is called much like a function.
  • 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.  (It should really be treated as a keyword and not allowed as a name in other constructs, but the current tokenizer does not detect keywords.)
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 which prints only expressions of type int.
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 arrays are equal if and only if they are both the same object.
    • Bali does not support division by zero, NaN, or infinity.
arrays
  • When an array is declared, its initial value is null.
  • 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 readInt( ).  This function returns a value of type int.