Tokens that contain letters are case-sensitive; for example, int is an INT token, while Int is not.
White space consists of any sequence of the following:WLP4 programs are constructed by tokenizing (also called scanning or lexing) an ASCII string. To ensure a unique sequence of tokens is produced, the sequence of tokens is constructed by repeatedly choosing the longest prefix of the input that is either a token or white space. If the prefix is a token, it is added to the end of the WLP4 program token sequence. Then the prefix is discarded, and this process repeats with the remainder of the ASCII string input. This continues until either the end of the input is reached, or no prefix of the remaining input is a token or white space. In the latter case, the ASCII string is lexically invalid and does not represent a WLP4 program.
procedures → procedure procedures procedures → main procedure → INT ID LPAREN params RPAREN LBRACE dcls statements RETURN expr SEMI RBRACE main → INT WAIN LPAREN dcl COMMA dcl RPAREN LBRACE dcls statements RETURN expr SEMI RBRACE params → params → paramlist paramlist → dcl paramlist → dcl COMMA paramlist type → INT type → INT STAR dcls → dcls → dcls dcl BECOMES NUM SEMI dcls → dcls dcl BECOMES NULL SEMI dcl → type ID statements → statements → statements statement statement → lvalue BECOMES expr SEMI statement → IF LPAREN test RPAREN LBRACE statements RBRACE ELSE LBRACE statements RBRACE statement → WHILE LPAREN test RPAREN LBRACE statements RBRACE statement → PRINTLN LPAREN expr RPAREN SEMI statement → PUTCHAR LPAREN expr RPAREN SEMI statement → DELETE LBRACK RBRACK expr SEMI test → expr EQ expr test → expr NE expr test → expr LT expr test → expr LE expr test → expr GE expr test → expr GT expr expr → term expr → expr PLUS term expr → expr MINUS term term → factor term → term STAR factor term → term SLASH factor term → term PCT factor factor → ID factor → NUM factor → NULL factor → LPAREN expr RPAREN factor → AMP lvalue factor → STAR factor factor → NEW INT LBRACK expr RBRACK factor → GETCHAR LPAREN RPAREN factor → ID LPAREN RPAREN factor → ID LPAREN arglist RPAREN arglist → expr arglist → expr COMMA arglist lvalue → ID lvalue → STAR factor lvalue → LPAREN lvalue RPAREN
Errors in context-sensitive syntax are referred to as semantic errors below. A program that contains a semantic error is not a valid WLP4 program and cannot be compiled.
A procedure is any string derived from procedure or main. If it is derived from procedure, the name of the procedure is the lexeme of the ID in the grammar rule whose left-hand side is procedure. The name of the procedure derived from main is wain. A procedure is said to be declared from the first occurrence of its name in the string that makes up that procedure (i.e., once the name has been encountered in the procedure's header). The following semantic errors exist related to procedure declarations:
The procedure wain may not call itself recursively. However, this is actually enforced by the context-free grammar (since wain is a keyword, not an identifier, and therefore cannot appear as the ID in the procedure call rules factor → ID LPAREN RPAREN and factor → ID LPAREN arglist RPAREN) and therefore is not considered a semantic error.
Any ID in a sequence derived from dcl within a procedure p is said to be declared in p. Any ID derived from factor or lvalue within p is said to be used in p. The name of the ID is the lexeme of the ID token. String comparisons between names are are case sensitive; for example, "FOO" and "foo" are distinct.
The following semantic errors exist related to declarations and uses of IDs in a procedure.
An ID may have the same name as a procedure. If an ID x is declared in a procedure p, all occurrences of x within p refer to the ID x, even if a procedure named x has been declared. The same is true in the special case that p = x: a declared ID may have the same name as the procedure that contains it; in this case, all occurrences of ID refer to the variable, not the procedure. This rule means there is an additional semantic error related to procedures and IDs:
For example, the following program does not contain any semantic errors. The declaration of the ID p as a parameter of the procedure p, and the use of the ID p in the return expression of procedure p, are not issues, because within the procedure p the ID p refers to the parameter variable. Within wain, the ID p refers to the procedure, since no ID named p is declared in wain, so the procedure call p(a) is valid.
int p(int p) { return p; } int wain(int a, int b) { return p(a); }On the other hand, the following program contains a semantic error. Th only difference is the name of the second parameter of wain has been changed from b to p. Therefore, there is now an ID p declared in wain, so the procedure call p(a) in the return expression of wain is not valid.
int p(int p) { return p; } int wain(int a, int p) { return p(a); }
An ID whose name occurs in a sequence derived from dcl has a type, which is either int or int*:
Other IDs (particularly, the IDs corresponding to procedure names) do not have types and are said to be untyped.
Every procedure has a signature, which is a list of strings, each of which is either int or int*. The signature of a procedure is the sequence of strings int or int* that is derived from params. Note that this sequence may be empty. The signature indicates the number of arguments expected by the procedure, and the type of each argument.
Instances of the tokens NUM, NULL and the nonterminals factor, term, expr, and lvalue also have a type, which is either int or int*. The types of these tokens and nonterminals are determined by the following rules. If the conditions of a rule are not satisfied, the program contains a semantic error.
int wain(int, int); void println(int); int putchar(int); int getchar(void); // === Insert WLP4 Program Here === #include <stdlib.h> #include <stdio.h> int main(int argc, char** argv) { int a,b,c; printf("Enter first integer: "); scanf("%d", &a); printf("Enter second integer: "); scanf("%d", &b); c = wain(a,b); printf("wain returned %d\n", c); return 0; } void println(int x){ printf("%d\n",x); }
int wain(int*, int); void println(int); int putchar(int); int getchar(void); // === Insert WLP4 Program Here === #include <stdlib.h> #include <stdio.h> int main(int argc, char** argv) { int l, c; int* a; printf("Enter length of array: "); scanf("%d", &l); a = (int*) malloc(l*sizeof(int)); for(int i = 0; i < l; i++) { printf("Enter value of array element %d: ", i); scanf("%d", a+i); } c = wain(a,l); printf("wain returned %d\n", c); return 0; } void println(int x){ printf("%d\n",x); }
Note that putchar and getchar are provided by the C standard library, and their behaviour is as described by C.
There are some situations where the expected behaviour of a WLP4 program may differ from that of the C++ program shells above:
new
. In C++, this throws an exception. Since WLP4 does not have exceptions, a failed allocation in WLP4 returns NULL.
array+241
where the array has fewer than 241 elements. This is undefined behaviour in C++, but it is allowed in WLP4, because it is used by Marmoset to test your implementation of pointer comparisons. The expected behaviour in WLP4 is that the result is the same as other (non-out-of-bounds) pointer arithmetic expressions.
However, dereferencing an out-of-bounds pointer is undefined behaviour in both C++ and WLP4.wlp4c
that contains undefined behaviour may behave differently from the C++ program shells.