#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "front.h"
#include "parser.h"
void error();
//#include "parser.h"
/* Global Variable */
int nextToken;
char *tokenNames;
/* Local Variables */
static int charClass;
static char lexeme[100];
static char nextChar;
static int lexLen;
static FILE *in_fp;
/* Local Function declarations */
static void addChar();
static void getChar();
static void getNonBlank();
//static void error();
//extern int nextToken;
//static int lex();
/* main driver */
//int argc, char *argv[]
int main() {
printf("DCooke Analyzer :: R11760605 \n \n");
/* Open the input data file and process its contents */
if ((in_fp = fopen("front.in","r")) == NULL) {
printf("ERROR - cannot open front.in \n");
} else {
getChar();
do {
lex();
program();
//
// expr();
} while (nextToken != EOF);
}
return 0;
}
/*****************************************************/
/* lookup - a function to lookup operators and parentheses and return the
* token */
static int lookup(char ch) {
switch (ch) {
case '(':
addChar();
nextToken = LEFT_PAREN;
tokenNames = "LEFT_PAREN";
break;
case ')':
addChar();
nextToken = RIGHT_PAREN;
tokenNames = "RIGHT_PAREN";
break;
case '=':
addChar();
nextToken = EQUAL_OP;
tokenNames = "EQUAL_OP";
break;
case '<':
addChar();
getChar();
if (nextChar == '=') {
addChar();
nextToken = LEQUAL_OP;
tokenNames = "LEQUAL_OP";
}
else if(nextChar == '>'){
addChar();
nextToken = NEQUAL_OP;
tokenNames = "NEQUAL_OP";
} else {
ungetc(nextChar, in_fp);
nextToken = LESSER_OP;
tokenNames = "LESSER_OP";
}
break;
case '>':
addChar();
getChar();
if (nextChar == '=') {
addChar();
nextToken = GEQUAL_OP;
tokenNames = "GEQUAL_OP";
} else {
ungetc(nextChar, in_fp);
nextToken = GREATER_OP;
tokenNames = "GREATER_OP";
}
break;
case ';':
addChar();
nextToken = SEMICOLON;
tokenNames = "SEMICOLON";
break;
case ':':
addChar();
getChar();
if (nextChar == '='){
addChar();
nextToken = ASSIGN_OP;
tokenNames = "ASSIGN_OP";
}else{
ungetc(nextChar, in_fp);
nextToken = COLON;
tokenNames = "COLON";
}
break;
case '+':
addChar();
getChar();
if (nextChar == '+') {
addChar();
nextToken = INC_OP;
tokenNames = "INC_OP";
} else {
ungetc(nextChar, in_fp);
nextToken = ADD_OP;
tokenNames = "ADD_OP";
}
break;
case '-':
addChar();
getChar();
if (nextChar == '-') {
addChar();
nextToken = DEC_OP;
tokenNames = "DEC_OP";
} else {
ungetc(nextChar, in_fp);
nextToken = SUB_OP;
tokenNames = "SUB_OP";
}
break;
case '*':
addChar();
nextToken = MULT_OP;
tokenNames = "MULT_OP";
break;
case '%':
addChar();
nextToken = MOD_OP;
tokenNames = "MOD_OP";
break;
case '/':
addChar();
nextToken = DIV_OP;
tokenNames = "DIV_OP";
break;
case EOF:
nextToken = EOF;
return nextToken;
break;
default:
addChar();
nextToken = UNKNOWN;
tokenNames = "UNKNOWN";
break;
}
return nextToken;
}
/*****************************************************/
/* addChar - a function to add nextChar to lexeme */
static void addChar() {
if (lexLen <= 98) {
lexeme[lexLen++] = nextChar;
lexeme[lexLen] = 0;
} else {
printf("Error - lexeme is too long \n");
}
}
/*****************************************************/
/* getChar - a function to get the next character of input and determine its
* character class */
static void getChar() {
if ((nextChar = getc(in_fp)) != EOF) {
if (isalpha(nextChar))
charClass = LETTER;
else if (isdigit(nextChar))
charClass = DIGIT;
else
charClass = UNKNOWN;
} else {
charClass = EOF;
}
}
/*****************************************************/
/* getNonBlank - a function to call getChar until it returns a non-whitespace
* character */
static void getNonBlank() {
while (isspace(nextChar))
getChar();
}
/*****************************************************/
/* lex - a simple lexical analyzer for arithmetic expressions */
int lex() {
lexLen = 0;
getNonBlank();
char READ[] = "read";
char IF[] = "if";
char FI[] = "fi";
char ELSE[] = "else";
char THEN[] = "then";
//char WHILE[] = "while";
//char DO[] = "do";
char WRITE[] = "write";
switch (charClass) {
/* Parse identifiers */
case LETTER:
addChar();
getChar();
while (charClass == LETTER || charClass == DIGIT) {
addChar();
getChar();
}
if (strcmp(lexeme, READ) == 0) {
nextToken = KEY_READ;
tokenNames = "KEY_READ";
break;
} else if (strcmp(lexeme, IF) == 0) {
nextToken = KEY_IF;
tokenNames = "KEY_IF";
break;
} else if (strcmp(lexeme, FI) == 0) {
nextToken = KEY_FI;
tokenNames = "KEY_FI";
break;
} else if(strcmp(lexeme, ELSE) == 0){
nextToken = KEY_ELSE;
tokenNames = "KEY_ELSE";
break;
}else if(strcmp(lexeme, THEN) == 0){
nextToken = KEY_THEN;
tokenNames = "KEY_THEN";
break;
}else if (strcmp(lexeme, WRITE) == 0) {
nextToken = KEY_WRITE;
tokenNames = "KEY_WRITE";
break;
} else {
nextToken = IDENT;
tokenNames = "IDENT";
break;
}
/* Parse integer literals */
case DIGIT:
addChar();
getChar();
while (charClass == DIGIT) {
addChar();
getChar();
}
nextToken = INT_LIT;
tokenNames = "INT_LIT";
break;
/* Parentheses and operators */
case UNKNOWN:
lookup(nextChar);
getChar();
break;
/* EOF */
case EOF:
exit(0);
lexeme[0] = 'E';
lexeme[1] = 'O';
lexeme[2] = 'F';
lexeme[3] = 0;
break;
} /* End of switch */
if (nextToken != EOF) {
printf("%s\t%s\n", lexeme, tokenNames);
}
return nextToken;
} /* End of function lex */
void expr() {
term();
while (nextToken == ADD_OP || nextToken == SUB_OP) {
lex();
term();
}
}
void term() {
factor();
while (nextToken == MULT_OP || nextToken == DIV_OP || nextToken == MOD_OP) {
lex();
factor();
}
}
void factor() {
if (nextToken == IDENT || nextToken == INT_LIT) {
lex();
}else if(nextToken == INC_OP || nextToken == ADD_OP || nextToken == SUB_OP || nextToken == DEC_OP){
lex();
} else {
if (nextToken == LEFT_PAREN) {
lex();
expr();
if (nextToken == RIGHT_PAREN) {
lex();
} else {
error();
}
} else {
error();
}
}
}
void statements(){
if (nextToken == IDENT){
lex();
if(nextToken == ASSIGN_OP){
lex();
expr();
}else{
error();
}
}
else if(nextToken == KEY_READ){
lex();
if(nextToken == LEFT_PAREN){
lex();
if(nextToken == IDENT){
lex();
}else {
error();
}
if(nextToken == RIGHT_PAREN){
lex();
} else{
error();
}
}else{
error();
}
}
else if(nextToken == KEY_WRITE){
lex();
if(nextToken == LEFT_PAREN){
lex();
expr();
if(nextToken == RIGHT_PAREN){
lex();
}else{
error();
}
} else{
error();
}
}
else if(nextToken == KEY_IF){
lex();
cond();
if(nextToken == COLON){
lex();
if(nextToken == KEY_THEN){
lex();
statements();
u();
if(nextToken == NULL){
lex();
statements();
} else{
error();
}
}else if(nextToken == KEY_FI){
lex();
} else{
error();
}
} else{
error();
}
}
else{
if(nextToken == SEMICOLON){
lex();
if(nextToken != EOF){
statements();
}
} else{
error();
}
}
}
void cond(){
expr();
if(nextToken == LEFT_PAREN){
cond();
if(nextToken == RIGHT_PAREN){
lex();
} else{
error();
}
} else if(nextToken == GREATER_OP || nextToken == LEQUAL_OP || nextToken == GEQUAL_OP || nextToken == LEQUAL_OP || nextToken == NEQUAL_OP){
lex();
expr();
} else{
error();
}
}
void program(){
statements();
}
void u(){
if(nextToken == KEY_ELSE){
statements();
} else{
nextToken = NULL;
}
}
void error() {
//lex();
fprintf(stderr, "Error: Invalid character: nextToken: %s lexeme : %s\n", tokenNames,lexeme);
exit(1);
} Write, Run & Share C Language code online using OneCompiler's C online compiler for free. It's one of the robust, feature-rich online compilers for C language, running the latest C version which is C18. Getting started with the OneCompiler's C editor is really simple and pretty fast. The editor shows sample boilerplate code when you choose language as 'C' and start coding!
OneCompiler's C online editor supports stdin and users can give inputs to programs using the STDIN textbox under the I/O tab. Following is a sample C program which takes name as input and print your name with hello.
#include <stdio.h>
int main()
{
char name[50];
printf("Enter name:");
scanf("%s", name);
printf("Hello %s \n" , name );
return 0;
}
C language is one of the most popular general-purpose programming language developed by Dennis Ritchie at Bell laboratories for UNIX operating system. The initial release of C Language was in the year 1972. Most of the desktop operating systems are written in C Language.
When ever you want to perform a set of operations based on a condition if-else is used.
if(conditional-expression) {
// code
} else {
// code
}
You can also use if-else for nested Ifs and if-else-if ladder when multiple conditions are to be performed on a single variable.
Switch is an alternative to if-else-if ladder.
switch(conditional-expression) {
case value1:
// code
break; // optional
case value2:
// code
break; // optional
...
default:
// code to be executed when all the above cases are not matched;
}
For loop is used to iterate a set of statements based on a condition.
for(Initialization; Condition; Increment/decrement){
// code
}
While is also used to iterate a set of statements based on a condition. Usually while is preferred when number of iterations are not known in advance.
while(condition) {
// code
}
Do-while is also used to iterate a set of statements based on a condition. It is mostly used when you need to execute the statements atleast once.
do {
// code
} while (condition);
Array is a collection of similar data which is stored in continuous memory addresses. Array values can be fetched using index. Index starts from 0 to size-1.
data-type array-name[size];
data-type array-name[size][size];
Function is a sub-routine which contains set of statements. Usually functions are written when multiple calls are required to same set of statements which increases re-usuability and modularity.
Two types of functions are present in C
Library functions are the in-built functions which are declared in header files like printf(),scanf(),puts(),gets() etc.,
User defined functions are the ones which are written by the programmer based on the requirement.
return_type function_name(parameters);
function_name (parameters)
return_type function_name(parameters) {
//code
}