CS 433 - The Omg Report

Omg is a simple procedural programming language used as the input language for our compiler in CS 433, Spring 2008. Omg stands for "Our Mix of Grammars" (as well as a few other things.) Omg supports two basic types: integer (called "num") and boolean (called "boo", with values "yes" and "no"), as well as arrays of integers and booleans. The language also supports recursion, nested scopes, and variable declarations "on the fly". Parameters can be passed by value and by reference. Input and output of integers and characters is supported. Not in the language are records, pointers, floats, and strings. Omg's syntax is based on suggestions of the students in the class. The language is derived from subsets of C and Pascal, with some syntactic quirks.

Language details:

  1. Omg's keywords are: num boo yes no glob ret if else while mod or and not

  2. Omg's operators and reserved characters are:
    < <= > >= = <>     comparison operators
    + - * / mod arithmetic operators
    := assignment operator
    @ indicates pass-by-reference (like "&" in C++)
    ( ) { } [ ] grouping / array subscript (same as in Java)
    .. defines subscript range in array declaration
    , separates parameters and terminates conditions in "if" and "while"
    ; terminates statements

  3. Single-line comments start with "#" and extend to the end of the line.
    Multi-line comments start with "(:" and end with ":)"; they cannot be nested.

  4. The language is case-sensitive: "boo" is different from "Boo" (the former is a keyword, the latter is not).

  5. Variables are declared like in Java / C, e.g., "num i, j; boo b;".

  6. Array declarations include a subscript range after the type name: "num[0..7] x; boo[-2..2] z;". The range needs to be given as two integer constants.

  7. Basic variables can be initialized as they declared ("num x = 2 * y;), but arrays cannot.

  8. Variable declarations and statements can be interleaved (like in C++ and Java).

  9. Functions are declared like in C / Java; procedures are simply declared without a type. The return statement is "ret".

  10. Global variables can be declared before functions and procedures, but they cannot be initialized. They need to be prefixed with the keyword "glob".

  11. Integer and boolean parameters can be passed by value (e.g., "num a") or by reference (e.g., "num @a"). Array parameters are automatically passed by reference, without specifying the bounds (e.g. "num[] a"). Each parameter must be listed with a type (like in C / Java), e.g., "gcd(num a, num b)".

  12. "if" and "while" statements are like in C / Java, except the condition is terminated by a comma, rather than surrounded by parentheses.

  13. Execution starts with the parameterless procedure "omg()" (like "main" in C / Java). Command-line arguments are not supported.

  14. The functions num rdn() and num rdc() are provided for input; the procedures prn(num n) and prc(num c) are provided for output. The 'n' versions read/print integers; the 'c' versions read/print characters.

  15. Character constants are supported as 'c', where c is any character except a newline, a backslash, or a single quote. These three special characters are represented with '\n', '\\', and '\''. A character constant is simply an integer (the corresponding ASCII code) - that is, there is no type "char". Character constants come in handy in conjunction with the prc procedure.


Here are some sample Omg programs:

# gcd.omg
# asks user for two integers and prints their GCD

num gcd(num a, num b) { # compute the GCD of a, b recursively
    if b > a,
        ret gcd(b, a);
    else if b = 0,
        ret a; 
    else
        ret gcd(b, b mod a);
}

omg() {   # main program
    prc('?');
    num x := rdn();   # get first number from user
    prc('?');
    num y := rdn();   # get second number from user
    prc('G'); prc('C'); prc('D'); prc('=');
    prn(gcd(x, y));
}

----------------------------------------------------------------------
(: reverse.omg
   reverses string entered by the user
:)

glob num newline;  # global variable

rev() {
    num c := rdc();         # read first character
    if c <> newline,
        rev();              # reverse rest of string
    prc(c);                 # print first character
}

omg() {
    newline := '\n';
    prc('?');
    rev();
    prc(newline);
}

----------------------------------------------------------------------

# bubble.omg
# bubble sort of 5 integers

swap(num @a, num @b) { # swaps a and b, which are passed by reference
    num tmp := a;
    a := b;
    b := tmp;
}

bubble(num[] X, num lo, num hi) { # sorts X[lo..hi] using bubble sort
    while hi > lo, {
        num j := lo;
        boo changed := no;
        while j < hi, {
            if X[j] > X[j+1], {
                swap(X[j], X[j+1]);
                changed := yes;
            }
            j := j + 1;
        }
        if not changed, 
            ret;
        hi := hi - 1;
    }
}

omg() { # main program
    num[1..5] A;
    A[1] :=  6;
    A[2] := -2;
    A[3] := 44;
    A[4] :=  3;
    A[5] :=  5;
    bubble(A, 1, 5);
    prn(A[1]); prc(' ');
    prn(A[2]); prc(' ');
    prn(A[3]); prc(' ');
    prn(A[4]); prc(' ');
    prn(A[5]); prc('\n');
}