.. index:: single: ASL Description single: Language specification ASL Description =============== You must build a compiler of ASL (*A Simple Language*), an imperative high-level programming language with the basic data types (integer, boolean, character, float), usual control structures (if-then-else, while, functions, ...), and arrays (one-dimension, basic type elements). Here you will find a definition of the syntax of the language, and the expected behavior of the compiler in most frequent situations. You will be provided example test suites with the errors that the compiler is expected to produce in each case. -------------------------------------------------------------------- Data types and variable declarations ------------------------------------ Variables must be declared before being used. Variable declarations can appear exclusively at the beggining of a function, and have the form: :: var id1, id2, .., idn : type Valid identifiers start by a letter, optionally followed by any string made of letters, digits, or underscores. Valid types for variables include basic --or primitive-- types, as well as arrays. Basic types are: - ``int`` : Integer - ``float`` : Real - ``bool`` : Boolean - ``char`` : Character Arrays can contain elements of basic types only, and are defined as follows: ``array [] of `` (where ```` is an integer constant determining the number of elements and ```` is a basic type). Examples of declarations: :: var a, b : int var a3, b_2, c3_x_ : bool var x : float var p, q : array [10] of char Literal values of type ``int`` consist of one or more digits. Literal values of type ``float`` consist of one or more digits followed by a decimal point, followed by one or more digits. Literal values of type ``bool`` are ``true`` and ``false``. Literal values of type ``char`` are enclosed in single quotes, e.g. ``'a'``, ``'5'``, ``'@'``. Escaped characters ``'\n'``, ``'\t'``, and ``'\''`` are allowed. -------------------------------------------------------------------- Functions, parameters, and results ---------------------------------- Functions are declared using keywords ``func`` and ``endfunc``. A comma-separated list of parameters (which maybe empty) is defined in parenthesis after the function name. For each parameter, name and type must be provided (i.e. brief parameter declaration of the form ``x,y:int`` is not allowed). Finally, the return type of the function (if any) is declared after a colon. Functions can only return basic types. All parameters are passed by value, except arrays, which are passed by reference. Integer values can be passed as arguments to float parameters, in which case an implicit conversion to float is performed. Declaration of local variables is located at the beggining of the function, following by the instructions in the function body. Functions (either void or not) may include ``return`` instructions at any point, with an argument of the appropriate type (or nothing for void functions). Integer values can be returned inside float functions, and an implicit cast is performed. Example of a function with boolean result: :: func fun1 (a: array [10] of int, b: float) : bool var i : int var x : bool i = 5; if a[i]>b then return a[i+1]!=a[i-1]; else x = false; return a[i-2]>0 or x; endif endfunc Example of a *void* function: :: func fun2 (a: array [10] of int, i: int) var i : int i = 5; if a[i]>b then a[i+1] = a[i-1]; return; else x = false; endif return; endfunc Functions that do not return a value can be called only as instructions. Functions returning a value can be called either inside expressions, or as instructions. In the later case, the return value is ignored. -------------------------------------------------------------------- Operators and precedence ------------------------ ASL supports all usual aritmethic, relational, and boolean operators, with the following precedences and left associativity: +-----------------------------------------------+--------------+ | *Operation* | *Precedence* | +===============================================+==============+ | ``[]`` | Highest | +-----------------------------------------------+--------------+ | ``not`` ``+`` ``-`` (used as unary operators) | | +-----------------------------------------------+--------------+ | ``*`` ``/`` ``%`` | | +-----------------------------------------------+--------------+ | ``+`` ``-`` | | +-----------------------------------------------+--------------+ | ``==`` ``!=`` ``>`` ``>=`` ``<=`` ``<`` | | +-----------------------------------------------+--------------+ | ``and`` | | +-----------------------------------------------+--------------+ | ``or`` | Lowest | +-----------------------------------------------+--------------+ As customary, these precedences may be overriden enclosing subexpressions in parenthesis. All relational operators can be applied to all basic types, except booleans, that admit only ``==`` and ``!=``. Numeric types (float and int) can also be compared (after performing an implicit conversion to float). Module operation (``%``) can only be applied to integer operands. The expected behaviour for negative operands is the same than in C++. When integer values are aritmethically operated with float values, an implicit conversion to float is performed before the actual operation, and the result of the operation has type float. -------------------------------------------------------------------- Basic instructions ------------------ Basic instructions include assignment, ``return`` statement, and read/write statements. All basic instructions must end in a semicolon ``;`` Assignment ^^^^^^^^^^ :: var x,y,i,j : int var a,b,c : array [10] of int x = 0; y = 2 + x; a[i+1] = x*2 - b[j]; c = a; Both primitive types and arrays can be assigned. Integer values can be assigned to float variables after an implicit conversion (but not the other way round). Input/output statements ^^^^^^^^^^^^^^^^^^^^^^^ * **Read** : reads a value from the standard input and stores it in given l-value. If the type of the input data does not match the l-value, the behaviour is undefined. Example: :: read x; * **Write** : prints to the standard output the value of given expression. Example: :: write x+2; write '\n'; Output statement ``write`` accepts also a string literal. This is the only use of string allowed in ASL. Example: :: write "The result is: "; write x+2; write '\n'; Return statement ^^^^^^^^^^^^^^^^ Return statement causes current function to stop execution and return to the caller. If the function has a return value, the result expression must be given as argument to the ``return`` instruction. This instruction can appear anywhere in a function. If the function contains paths not ending in a ``return`` instruction, the function will return an undefined value when reaching the end of its code. Examples: :: func f() : bool ... ... return x>0 or not b; endfunc func g() ... if (err!=0) then return; endif ... endfunc -------------------------------------------------------------------- Control structures ------------------ ASL has two control structures: one for alternative composition and one for iterative composition: * Alternative composition: alternative statements can be built with keywords ``if``, ``then``, ``else``, and ``endif``. The condition must be of boolean type. The ``else`` branch is optional. Example of an ``if-then-else`` construction :: if a>b then x = 0; else x = 2 + y; endif Examples of ``if-then`` constructions :: if x+1<0 then a=b; endif * Iterative statements may be expressed with the ``while-do-endwhile`` construction The condition must be of boolean type. Example of ``while-do-endwhile`` construction :: while a>0 do s = s + a; a = a - 1; endwhile