# Reference Manual
### **Contents:**
* [Lexical Conventions](#Lexical-Conventions)
* [Identifiers](#Meaning-of-Identifiers)
* [Conversions](#Conversions)
* [Expressions](#Expressions:-(Operators))
* [Declarations](#Declarations)
* [Statements](#Statements)
* [Functions](#Function)
* [Scope and linkage](#Scope-and-linkage)
* [Preproccessing](#Preproccessing)
## Lexical Conventions
PIE is read by a parser and then before compiling it is passed through Lexical analyser to which the program written by the user is input and a sequence of tokens is output. More detailed analysis is done in PREPROCESSING section.
### TOKENS
There are broadly 6 classes: identifiers, keywords, constants,string literals,operators and other separators. WHITESPACE tokens are ignored except that they separate tokens. Some whitespace is required to separate otherwise adjacent identifiers, keywords and constants. If the input stream has been separated into tokens upto a given character, the next token is the longest string of characters that could constitute a token.
### COMMENTS
There are two ways of writing comments. Comments are just written for the user readability. The Lexical analyser simply ignores the comments. In case of single line comments we use // to start a comment. In case of multi line comments we start with /* and end with */.
### IDENTIFIERS
Identifiers are sequence of letters and digits. The first character must be a letter or underscore _ . Letters are case sensitive. KEYWORDS AS IDENTIFIERS IS STRICTLY PROHIBITED. They are used to bind memory to a constant.
### KEYWORDS
Keywords basically are some of the primitives of the language (not exclusively). The following identifiers are reserved for keywords and otherwise they shouldnot be used.
* *Let , until , execute,
decimal, integer, list
register , string , character,
if , else if , else,
Iterations,return,custom_type ,decimal(s), void,break,switch
boolean,bit,byte,set,auto,fast,longlife,switch,goto*
### CONSTANTS
There are several kinds of constants. Each has a data type.
* *Constant:
Integer- constant
Character-constant
Decimal- constant*
* * Integer constants:-
An integer constant consists of a sequence of digits. By default the numbers are represented in base 10 representation.
* Character constants:-
A character constant is a sequence of one or more characters enclosed in a single quote as in 'x'. The value of a character constant with only one character is the numeric value of the character in the machine's character set at execution time. The value of a multicharacter constant is implementation defined.
Character constants don't contain the ' character or newlines; inorder to represent them and certain other characters the following escape sequences may be used.
| Column 1 | Column 2 |
| -------- | -------- | -------- |
| newline | \n | Text |
| Horizontal tab | \t| Column 3 |
| Vertical tab | \v | -------- |
| Backspace | \b | Text |
| Carriage return | \r | Column 3 |
| form feed | \f | -------- |
| Audible alert | \a | Text |
| Backlash | \\| Column 3 |
| Question mark | \ ? | -------- |
|Single quote | \ ' | Text |
| Double quote | \ " | Column 3 |
### DECIMAL CONSTANTS:-
Decimal constants are sequence of base 10 numerals.
They are also by default represented in base 10 notation.
### STRING CONSTANTS:-
String can be thought of as an array of characters enclosed in a double quote "...".
A string ends by a special character \0 which indicates end of string.
## Meaning of Identifiers
identifiers represent the name in the program, for example, variables, functions, arrays, structures, unions, labels, tags of structures, enumerations, typedef names and objects.
Objects or variables act as a location in storage, interpretation depends on 2 attributes; “storage class” and “types”.
Storage classes determine whether : the object has internal, external, or no linkage. The type determines the meaning of the values found in identified object.
### Storage class specifiers
* *auto* : This specifier lets you explicitly declare a variable with automatic storage. It is a default for variables inside the block. A variable X that has automatic storage is deleted when the block in which X was declared exists.
* *fast* : This specifier tries to keep the variables in the cpu register.
* *longlife* : This specifier can make the life time (not necessarily visible time / binding time) large.
* *array*
* *function*
* *longstorage*
* *memorised function*:This specifier is used only for return(nonvoid) functions, when ever this function called again with already used arguments will directly return the value without computation .all the results of function with arguments called will be stored in the memory.
By default without any storage class specifier, in the declaration it is taken as “auto”
### Type specifiers / Qualifiers
Type specifiers :
* *void(s)* : The void type specifies an empty set of values. It is used as the type returned by functions that generate no value.
* *integer(s)*: range is 2 bytes - 2 * 8 bits
-32768 to 32767
* *decimal(s)*
* *character*
* *boolean(s)*
* *string(s)*
* *bit(s)*
* *byte(s)*
* *set*
Type Qualifiers :
Constant:
Type qualifiers may appear with any type specifier and type specifiers are mandatory for every declaration, failing to do so will throw a error.
Formating specifiers in system calls:
|type | format |
| -------- | -------- |
|integer | ${I.a} |
|string | ${S.a} |
| decimal | ${D.a} |
| boolean(s) | ${T.a} |
| bit(s) | ${b.a} |
| byte(s) | ${B.a} |
| set | ${L.a} or ${I.L.a} |
|character|${C.a}|
## Conversions
Many problems need conversion in programming, few operands are converted to other types depending on the problem statement. Here we are going to summarize conversions of operands accordingly.
### Integral Promotions
While declaration whether its a character or integer all either signed or not, may be used in an expression.
Ex:
let a be integer
Here the later part integer represents all the values of the original type, then the value is corrected to integer else it will be converted to unsigned integer. This is integral promotion
### Integral conversions
Integer is converted to a given unsigned type by finding the smallest non-negative value that is congruent to the integer value. Modulo is another unsigned type which represents the largest value.
When any integer is converted to a signed type, the value is unchanged if it can be represented
in the new type and is implementation-defined otherwise.
### Integer and Decimal
Decimal converting decimal to integer gives only the integer part where the decimal part is discarded. In the same manner if integral is converted into decimal the precision of the decimal alters and the value(remains same) will be within the range. If the result is out of range, then the behaviour is undefined
### Decimal types
Conversion among decimals leads to change in the precision; it can be a little higher or it can be lower. While converting less precise decimal to higher precise the value doesn't change whereas the reverse yields a change in the value it can be a little higher or it can be a little lower value. If the result is out of range, the behaviour is undefined
### Arithmetic conversions
Solving a problem sometimes results in change of the result type. But the process is to bring the operand into a similar type, this is called as usual arithmetic conversions.
Here having integer gives us a large range of them decimals are also in the same way if any operand is less precise and the other more precise then during the conversion the other operand which has less precise value changes accordingly with the other operand with high precise value thus the operation works.
### Void
Void itself tells that its null or nonexistent value thus a void object may not be used in any way, Let's call a statement where there are no expressions needed there we call the void
Ex:
```js
let main be void function
let fun be integer function
{
print it: “Hello World”
}
```
The above function does not need any value hence void used here. Henceforth by using void there will be no conversion a void type to other non-void types as its nonexistent.
## Expressions: (Operators)
The order of precedence of each expression is the same as
the order topic that is discussed in the following sections, that is, precedence of
operator(expression) discussed in section 7.1 is more than that of the operator
discussed in section 7.3. In each section the associative property of each
expression operator is mentioned. In the case of operators with same
precedence are used then the associativity of the operators comes into picture.
### Parenthesis:
In the PIE language, the parenthesis expression has the
highest precedence, hence operations in the parenthesis i.e. in ( ), [ ], { } are
evaluated first. Its associativity is from left to right.
### Exponent:
The symbol of exponent operator is ‘^’ (without quotes). Its associativity is from left to right. The operator is applied only to the integral
operands. a^b is read as a to the power of b, here both operands a and b must
be integers and the result of the operation will also be an integer. Its associativity
is from left to right.
### Multiplicative operators:
/,*,% belongs to this category, these symbols
correspond to quotient (gives quotient of resultant division),multiplication,
remainder ( gives remainder of resultant division) operations. In all these cases
the operands of the operation should belong to integer or decimal data type and
also the result of these operations as well belongs to decimal or integer data
type. Associativity of each operator in this section is from left to right.
### Bit shift operators:
Left bit shift operator (symbol ‘<<’) and right bit shift operator (symbol ‘>>’) fall under this category. The 2 operands of this operation
must be from integer data type (only positive integers) and the result will also be
in the same datatype. Simply the result of a>>b is that, the integer ‘a’ is multiplied
by ‘2^b’ and the result of a<<b is that, the integer ‘a’ is divided by ‘2^b’, only
quotient is considered as end result in this case. Associativity of each operator is
from left to right. If both these operators are used next to each other (adjacently)
then the picture of associativity comes.
### Bit wise AND:
Symbol is ‘&’. The operands should be of integer data type. The result is bit wise AND function of the 2 operands, the result of this operation
is also of integer data type. Its associativity is from left to right.
### Bit wise exclusive OR:
Symbol is ‘@’. The operands should be of integer data type. The result is bit wise exclusive OR function of the 2 operands, the
result of this operation is also of integer data type. Its associativity is from left to
right.
### Bit wise OR:
Symbol is ‘#’. The operands should be of integer data type.
The result is bit wise OR function of the 2 operands, the result of this operation is
also of integer data type. Its associativity is from left to right.
### Logical AND:
Symbol is ‘&&’. Consider example, a&&b. The ‘&&’ operator first evaluates ‘a’ if it is false then it doesn’t evaluate the contents in ‘b’ and finally
returns 0. This operator evaluates ‘b’ only if ‘a’ is already true and finally returns 0
if ‘b’ is false otherwise returns ‘1’ if both ‘a’ and ‘b’ are ture. The ‘&&’ operator
returns integer data type results (either 1 or 0 but not both). Its associativity is
from left to right.
### Logical OR:
Symbol is ‘##’. Consider example, a##b. The ‘##’ operator first evaluates ‘a’ if it is true then it doesn’t evaluate the contents in ‘b’ and finally
returns 1. This operator evaluates ‘b’ only if ‘a’ is already false and finally returns
0 if ‘b’ is false otherwise returns ‘1’ if atleast one of a and b is true. The ‘##’
operator returns integer data type results (either 1 or 0 but not both). Its
associativity is from left to right.
### Assigning and Comparing operators:
The operators that fall under this category are = (a=b ; assigning value of b to a), == (a==b; checking whether a
and b are equal), <, <=, >, >=, != (less than, less than or equal to, greater than,
greater than or equal to, not equal to). The operands of these operators can be of
any data type or any abstract data type. Its associativity is from left to right.
### Precedence Table
Precedence table with associativity and precedence decreasing from top to bottom. Operators in the same group has same precedence value.
| OPERATOR | MEANING | ASSOCIATIVITY |
| --------------- | ----------------------------------- | ------------- | ---
| ( ),[ ] | Parenthesis | Left to Right | |
| ^ | Text | Left to Right | |
| /,*,% | division,multipication,remainder | Left to Right | |
| <<,>> | left,right shift bit operator | Left to Right | |
| & | bitwiseAND | Left to Right | |
| @ | Bitwise execulsive OR | Left to Right | |
| ==,<,>,<=,>=,!= | Comparing | Left to Right | |
| # | Bitwise OR | Left to Right | |
| && | Logical AND | Left to Right | |
| ## | Logical OR | Left to Right | |
| &_& | Logical AND(without Shortcircuting) | Left to Right | |
| #_# | Logical OR(without Shortcircuting) | Left to right | |
| = | Assignment | Right to Left | |
## **Declarations**
----
Declarations are used to interpret the nature of identifier but do not necessarily consume spcae.
Declarations have the form
>*declaration:\
let declaring-list*
* *declaring-list:\
declaring\
declaring,declaration-list*
* *declaring:\
**init-declarator-list** be **declaration-specifiers-list***
* *init-declarator-list:\
init-declarator\
init-declarator-list , init-declarator*
* *init-declarator:\
declarator\
declarator = initializer*
* *declaration-specifers:*\
*storage-class-specifier declaration-specifiers<sub>opt</sub>\
type-specifier declaration-specifiers<sub>opt</sub> reference<sub>opt</sub>\
type-specifier (ordered-pair) declaration-specifiers<sub>opt</sub>\
type-qualifier declaration-specifiers<sub>opt</sub>*
### **Storage class specifiers**
* Storage class Specifiers:
* auto
* fast
* longlife / memorised
* array
* function
* *fast* specifer tries to keep the variables in the cpu register
* *longlife* specifier can make the lifetime(not nesscarily visble time/binding time) large
* By default wihout any storage class specifier in the declarations it is taken as auto
### **Type specifiers / Qualifiers**
* Type Specifiers
* void(s)
* integer(s)
* decimal(s)
* boolean(s)
* string(s)
* bit(s)
* byte(s)
* character
* Type Qualifiers
* constant
* Type qualifiers may appear with any type specifier
* Type Specifiers are mandatory for every declaration, failling to do so will throw a error
### **Declarators**
* *declarators:\
identifier\
identifier (parameter-list)*
### **Intiallisation**
When an object is declared, its init-declarator may specify an initial value for the identifier
being declared. The initializer is preceded by =, and is either an expression, or a list of
initializers nested in braces
* *initializer:\
assignment-expression\
{ initializer-list }\
{ initializer-list , }*
* *initializer-list:\
initializer\
initializer-list , initializer*
### **Type names**
Type names are needed when for passing types names for type-casting / function parameters etc..
*type_name:\
type-specifer*
### **Custom type declarations**
* A Custom type is an object consisting of a sequence of named members of various types.
* *let identifier be[\
members-list\
]*
* *members-list:\
member,\
members-list*
* *member:\
declaring*
### **Examples**
```js
let a=5,b=102 be constant integers
/*
a=5,b=5 --> init-declarator-list
a=5 and b=5 are --> init-declarators
5,102 --> intializers
"constant integers" --> declartion-specifier-list
"constant" and "integers" --> declaration-specifier
^^ ^^
|| ||
Qualifier Specifier
*/
```
```c
let add(a as integer, b=5.2 as decimal) be decimal function
/*
add(a as integer, b=5.2 as decimal) --> init-declarator
(a as integer, b=5.2 as decimal) --> parameter-list
5 --> intializers // Here it is default argument
"decimal function" --> declartion-specifier-list
"decimal" and "function" --> declaration-specifier
^^ ^^
|| ||
Specifier Specifier
*/
```
```js
let Node be [
let key be integer,
let parent,chlid be Nodes refernce,
]
//Parent and child can be intialised using new to create 'Refernce model' variables
/*
let key be integer, ---|members-list
let parent,chlid be Nodes, ---|
Node --> identifier
*/
-------
```
## Statements
Statements are executed in a sequence.Statements are executed for their effect, and do not have values.They fall into several groups
Statements :
- labeled-statement
- expression-statement
- selection statement
- iteration statement
- Jump statements
### Labeled statements
Each statement in a program can be labeled.A label is an identifier added before the statement like this:
"label_identifier: statement: "
There is no special declaration of label - it just "tags" the " statement.Label_identifier " has a function scope and the same label cannot be redefined within the same function.
Labels have their own namespace: label identifier can match any other identifier in the program.
### Expression statements
Most of the statements are expression statements. An expression statement is simply an expression,which is of form
* *expression-statement:\
expression*
The lines
i = 0
i = i + 1
and
print it:"Hello world"
are all expression statements.
Expression statements do all of the real work in a PIE program. Whenever you need to compute new values for variables, you'll typically use expression statements (and they'll typically contain assignment operators). Whenever you want your program to do something visible, in the real world, you'll typically call a function (as part of an expression statement). We've already seen the most basic example: calling the function "print it:" to print text to the screen. But anything else you might do--read or write a disk file, talk to a modem or printer, draw pictures on the screen--will also involve function calls.
Expressions and expression statements can be arbitrarily complicated. They don't have to consist of exactly one simple function call, or of one simple assignment to a variable. For one thing, many functions return values, and the values they return can then be used by other parts of the expression.
### Selection statements
Selection statements choose one of the several flows of control.
* *selection statements:\
if {declarative-list opt condition} execute {body}
if {declarative-list opt condition} execute {body}
else execute {body}
if {declarative-list opt condition} execute {body}
else if {declarative-list opt condition} execute {body}
else execute {body}
switch{case}
{
condition: declerative list
condition2:declerative list
}*
The statement following the control condition is executed if the value of the control condition is true (nonzero).
An if statement can be written with an optional else clause that is executed if the control expression is false (0).
An if statement can be written with an optional else if clause that is executed if the control expression is false and the condition in the else if is true.This else if's can be many as our convenience.After all else if condition' s are false then only else condition is executed.
### Iteration statements
Iteration statements specify looping.
* *iteration-statement:\
until {condition} execute {body}\
until {initialize} {condition} execute {body}*
In the until {condition} execute {body} statements,the substatement is executed repeatedly so long as the value of the condition remains unequal to 0.
The until {condition} execute {body} evaluates the condition before executing the loop body.
In the until {initialize} {condition} execute {body} statements,the substatement is executed repeatedly so long as the value of the condition remains unequal to 0.The inititialize contains both the initial value and the changing value.The initial value is evaluated once and the changing value expression and the condition is evaluated in each iteration.There is no restriction on the type.
### Jump Statements
* *return (expression/value);*
* *break- this statement will break out of loop*
## Function
* *Function Defination:
let declerator be declerator-declaration-specifiers classtype compound-statement*
class type is only function.all function arguments are passed as reference.A function may return an arithmetic type, string or void, but not a function or an array.declerator is of form of parameter type list the declaration-list following the function's.declarator must be absent.Unless the parameter list soley of void shows that function has no parameters.each declerator in parameter list should contain a indentifier.parameter list could also contain indentifier function . non argument functions don't have declerator.
* *direct-declarator ( parameter-type-list)
direct-declearator
/*without parameter list meaning parameter list is void*/*
#### Example:
```js
let convert(n as integer) be integer function
/* ^^^^^ ^^^ ^^
declerator (parametertypelist ) specifier
*/
{
let dec=0 be integers //variable initialization
return dec as integer //dec(integer returning)
}
/*{ ... } is the block giving the code for the function.*/
```
## Scope and linkage
Communication among the functions of a program may be carried out both through calls and through manipulation of external data.Therefore, there are two kinds of scope to consider: first, the lexical scope of an identifier.which is the region of the program text within which the identifier's characteristics are understood; and second, the scope associated with functions with external linkage,which determines the connections between identifiers in separately compiled translation units.
### Lexical scope
Identifiers fall into several name spaces that do not interfere with one another; the same identifier may be used for different purposes, even in the same scope, if the uses are in different name spaces.
The lexical scope of a function identifier in an external declaration begins at the end of its declarator and persists to the end of the translation unit in which it appears. The scope of a parameter of a function definition begins at the start of the block defining the function, and persists through the function; the scope of a parameter in a function declaration ends at the end of main program. The scope of an identifier declared at the head of a block begins at the end of its declarator, and persists to the end of the block. The scope of a label is the whole of the
function in which it appears.If an identifier is explicitly declared at the head of a block, including the block constituting a function, any declaration of the identifier outside the block is suspended until the end of the
block.
### Linkage
Within a translation unit,all declarations of the same function identifier with internal linkage refer to the same thing,and function is unique to that translation unit.There are no external linkages.all function parameters are linked between main program and function calling as arguments are called by reference.
### Preproccessing
The user written code is not ready to be compiled as such.
It is passed through a Parser and a Lexical analyser. A Lexical analyser can be thought of as level of abstraction sitting between user code and compiler. After the user code is passed through the parser it identifies the Functions from one of the 3 standard libraries which can be thought of included in the KERNEL of PIE language. Any other standard libraries can be thought of as an extension and should be explicitly mentioned in the user by using Checkin keyword. The 3 standard libraries are input-output library(consists both of sdin,sdout as well as console input output), maths library, resource allocation library ( for dynamic memory or implicit stack abstraction ).
As the user code is passed into parser it notes the functions which are undefined and checks them in standard libraries. If they are not present it throws an error before even the compilation happens. If they are present then it is passed to Lexical analyser which in first place checks the syntax and incase of an invalid syntax throws an error. If the syntax is valid one it expand the program including the libraries and functions and reduces it to basic set of primitives which is ready for compilation.