Lab Programs
Lab Programs
#include<stdio.h>
#include<conio.h>
#include<ctype.h>
#include<string.h>
#include<stdlib.h>
#define SIZE 128
#define NONE -1
#define EOS ‘\0’
#define NUM 256
#define KEYWORD 257
#define PAREN 258
#define ID 259
#define ASSIGN 260
#define REL_OP 261
#define DONE 262
#define MAX 999
char lexemes[MAX];
char buffer[SIZE];
int lastchar = -1;
int lastentry = 0;
int tokenval=NONE;
int lineno=1;
struct entry
{
char *lexptr;
int token;
}symtable[100];
void Initialize()
{
struct entry *ptr;
for(ptr=keywords;ptr->token;ptr++)
insert(ptr->lexptr,ptr->token);
}
int lexer()
{
int t;
int val,i=0;
while(1)
{
t=getchar();
if(t == ’’ || t==’\t’);
else if(t==’\n’)
lineno++;
else if(t == ’(‘ || t == ‘)’)
return PAREN;
else if(t==‘<’ ||t==‘>’ ||t==‘<=’ ||t==‘>=’ ||t == ‘!=’)
return REL_OP;
else if(t == ’=’)
return ASSIGN;
else if(isdigit(t))
{
ungetc(t,stdin);
scanf(“%d”,&tokenval);
return NUM;
}
else if(isalpha(t))
{
while(isalnum(t))
{
buffer[i]=t;
t=getchar();
i++;
if(i>=SIZE)
Error_Message(“compiler error”);
}
buffer[i]=EOS;
if(t!=EOF)
ungetc(t,stdin);
val=look_up(buffer);
if(val==0)
val=insert(buffer,ID);
tokenval=val;
return symtable[val].token;
}
else if(t==EOF)
return DONE;
else
{
tokenval=NONE;
return t;
}
}
}
void main()
{
int lookahead;
char ans;
clrscr();
printf(“\n]t]t Program for Lexical Analysis \n”);
Initialize();
printf(“\n Enter the expression and put ; at the end”);
printf(“\n Press Ctrl + Z to terminate... \n”);
lookahead=lexer();
while(lookahead!=DONE)
{
if(lookahead==NUM)
printf(“\n Number: %d”,tokenval);
if(lookahead==’+’|| lookahead==’-’|| lookahead==’*’||
lookahead==’/’)
printf(“\n Operator”);
if(lookahead==PAREN)
printf(“\n Parentesis”);
if(lookahead==ID)
printf(“\n Identifier: %s“,
symtable[tokenval].lexptr);
if(lookahead==KEYWORD)
printf(“\n Keyword);
if(lookahead==ASSIGN)
printf(“\n Assignment Operator”);
if(lookahead==REL_OP)
printf(“\n Relataional Operator”);
lookahead=lexer();
}
}
OUTPUT:
Keyword
Parenthesis
Identifier: a
Relational Operator
Identifier: b
Parenthesis
Identifier: a
Assigment Operator
Identifier: a
Operator
Identifier: b
^Z
2. Develop a recursive decent parser
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
#include<string.h>
char lexemes[MAX];
char buffer[SIZE];
int lastchar=-1;
int lastentry=0;
int tokenval=DONE;
int lineno=1;
int lookahead;
struct entry
{
char *lexptr;
int token;
}symtable[100];
struct entry keywords[]={"if",KEYWORD,"else",KEYWORD,"for",KEYWORD,
"int",KEYWORD,"float",KEYWORD,"double",KEYWORD,
"char",KEYWORD,"struct",KEYWORD,"return",KEYWORD,
0,0};
void initialise()
{
struct entry *ptr;
for(ptr=keywords;ptr->token;ptr++)
insert(ptr->lexptr,ptr->token);
}
int lexer()
{
int t;
int val,i=0;
while(1)
{
t=getchar();
if(t==' '||t=='\t');
else if(t=='\n')
lineno=lineno+1;
else if(isdigit(t))
{
ungetc(t,stdin);
scanf("%d",&tokenval);
return NUM;
}
else if(isalpha(t))
{
while(isalnum(t))
{ buffer[i]=t;
t=getchar();
i=i+1;
if(i>=SIZE)
errormsg("compile error");
}
buffer[i]=EOS;
if(t!=EOF)
ungetc(t,stdin);
val=lookup(buffer);
if(val==0)
val=insert(buffer,ID);
tokenval=val;
return symtable[val].token;
}
else if(t==EOF)
return DONE;
else
{ tokenval=NONE;
return t;
}
}
}
void match(int t)
{
if(lookahead==t)
lookahead=lexer();
else
errormsg("syntax error");
}
void F()
{ void E();
switch(lookahead)
{
case '(':
match('(');
E();
match(')');
break;
case NUM:
display(NUM,tokenval);
match(NUM);
break;
case ID:
display(ID,tokenval);
match(ID);
break;
default:
errormsg("syntax error");
}
}
void T()
{ int t;
F();
while(1)
{ switch(lookahead)
{
case '*':
t=lookahead;
match(lookahead);
F();
display(t,NONE);
continue;
case '/':
t=lookahead;
match(lookahead);
F();
display(t,NONE);
continue;
default: return;
}
}
}
void E()
{ int t;
T();
while(1)
{ switch(lookahead)
{
case '+':
t=lookahead;
match(lookahead);
T();
display(t,NONE);
continue;
case '-':
t=lookahead;
match(lookahead);
T();
display(t,NONE);
continue;
default:
return;
}
}
}
void parser()
{
lookahead=lexer();
while(lookahead!=DONE)
{
E();
match(';');
}
}
int main()
{
char ans;
clrscr();
printf("\n \t \t Program for recursive decent parsing");
initialise();
printf("enter the expression & place;at the end \n Press CTRL
+ Z to terminate");
parser();
return 0;
}
OUTPUT:
Program for recursive decent parsing
number 2
number 3
number 4
arithmetic operator *
arithmetic operator +
2+3*4+5;
number 2
number 3
number 4
arithmetic operator *
arithmetic operator +
number 5
arithmetic operator +
a-b;
identifier a
identifier b
arithmetic operator –
+1
Line7: syntaxerror
3. Write a program for generating for various intermediate code forms:
● Three address code
● Quadruple
NUMBER [0-9]+
LETTER [a-zA-Z]+
%%
{NUMBER} {yylval.sym=(char)yytext[0];return NUMBER;}
{LETTER} {yylval.sym=(char)yytext[0];return LETTER;}
\n {return 0;}
{return yytext[0];}
%%
%{
#include<stdio.h>
#include<string.h>
int nIndex=0;
struct InterCode
{
char operand1;
char operand2;
char opera;
};
%}
%union
{
char sym;
}
ThreeAddressCode()
{
int nCnt=0;
char temp =’A’;
printf(“\n\n\t THREE ADDRESS CODE\n\n”);
temp++;
while(nCnt<nIndex)
{
printf(“%c : =\t”,temp);
if(isAlpha(Code[nCnt]].operand1))
printf(“%c\t”,Code[nCnt].operand1);
else
printf(“%c\t”,temp);
printf(“%c\t”,Code[nCnt].opera);
if(isAlpha(Code[nCnt]].operand2))
printf(“%c\t”,Code[nCnt].operand2);
else
printf(“%c\t”,temp);
printf(“\n”);
nCnt++;
temp++;
}
}
void Quadruples()
{
int nCnt=0;
char temp =’A’;
temp++;
printf(“\n\n\t QUADRUPLES\n”);
printf(“\n ID OPERATOR OPERAND1 OPERAND2 RESULT\n”);
while(nCnt<nIndex)
{
printf(“\n(%d)\t%c\t”,nCnt,Code[nCnt].opera);
if(isAlpha(Code[nCnt]].operand1))
printf(“%c\t”,Code[nCnt].operand1);
else
printf(“%c\t”,temp);
if(isAlpha(Code[nCnt]].operand2))
printf(“%c\t”,Code[nCnt].operand2);
else
printf(“%c\t”,temp);
printf(“%c\t”,temp);
nCnt++;
temp++;
}
}
main()
{
printf(“\nEnter The Expression”);
yyparse();
ThreeAddressCode();
Quadruples();
}
yywrap()
{
return 1;
}
Output:
[root@localhost]# lex intcode.l
[root@localhost]# yacc -d intcode.y
[root@localhost]# ./a.out
QUADRUPLES
ID OPERATOR OPERAND1 OPERAND2 RESULT
(0) / d e B
(1) * c B C
(2) + b B D
(3) = a B E
[root@localhost]# ./a.out
QUADRUPLES
ID OPERATOR OPERAND1 OPERAND2 RESULT
(0) * c d B
(1) / B e C
(2) + b B D
(3) = a B E
4. Write a program to generate the intermediate code in the form of Polish
Notation
#include<stdio.h>
#include<conio.h>
#include<string.h>
#incldue<stdlib.h>
struct stack
{char s[30];
int top;
}st;
void main()
{
char input[30];
void input_to_code(char infix[30]);
clrscr();
printf("\n Enter an input in the form of expression ");
scanf("%s",input);
input_to_code(input);
getch();
}
char pop()
{
char e;
e=st.s[st.top];
st.top--;
return e;
}
Output:
Enter an input in the form of expression (a+b)*(c-d)
/************************************************************
Program to perform various operations such as creation,
insertion, deletion, display of heap
*************************************************************/
#include<stdio.h>
#include<conio.h>
#include<stdlib.h>
#define TRUE 1
#include FALSE 0
node *create();
void main()
{
/*local declarations*/
int choice,val;
char ans;
node *head;
void display(node *);
node *search(node *,int);
node *insert(node *);
void dele(node **);
head=NULL;
do
{
clrscr();
printf(“\n Program to perform various operations on heap
using dynamic memory management”);
printf (“\n1.Create”):
printf (“\n2.Display”):
printf (“\n3.Insert an element in a list”);
printf (“\n4.Delete an element from list”);
printf (“\n5.Quit”);
printf (“\n Enter Your Choice(1-5)”);
scanf(“%d,&choice”);
switch(choice)
{
case 1:head=create();
break;
case 2:display(head);
break;
case 3:head=insert(head);
break;
case 4:dele(&head);
break;
case 5:exit(0);
default:clrscr();
printf(“Invalid Choice,Try again”);
getch();
}
}while(choice!=5);
}
node *create()
{
node *temp,*new,* head;
int val,flag;
char ans=’y’;
node *get_node();
temp=NULL;
flag=TRUE;
/*flag to indicate whether a new node is created for the first time
or not*/
do
{
printf(“\n Enter the Element”);
scanf(“%d”,&val);
/*allocate new node*/
new =get_node();
if(new==NULL)
printf(“\n Memory is not allocated”);
new-> data=val;
if (flag==TRUE)/* Executed only for the first time*/
{
head=new;
temp=head; /*head is the first node in the heap*/
flag=FALSE;
}
else
{
/*temp keeps track of the most recently created node*/
temp->next=new;
temp=new;
}
printf(\nDo you want to enter more elements?(y/n)”);
ans=getch();
}while(ans= = ‘y’);
/*
*The display function
*Input:Address of the first node of the list
*Output:Displays the list of allocated nodes
*Parameter Passing Method : call by value
*Called by main
**/
void display(node*head)
{
node *temp;
temp=head;
if(temp= =NULL)
{
printf(“\n The list is empty\n”);
getch();
clrscr();
return;
}
while(temp!= NULL)
{
printf(“%d->”,temp-> data);
temp=temp->next;
}
print(“NULL”);
getch();
clrscr();
}
/*
*The search function
*Input: Address of the starting node and the element which is
*to be searched
*Output:Searches for the element in list
*If found returns pointer to that node Otherwise NULL
*Parameter passing Method:call by value
*Called by:main
*Calls:None
**/
found=FALSE;
While(temp!= NULL && found= =FALSE)
{
if(temp->data != key)
temp = temp->next;
else
found = True;
}
if(found == TRUE)
{
printf(“\n The Elements is present in the list”\n);
getch();
return temp;
}
else
printf(“\n The Element is not present in the list\n”);
getch();
return NULL;
}
/*
*The insert function
*Input: Address of starting node of the list
*Output:inserts element into the list
*Parameter Passing Methods: call by value
*Called by : main
*Calls : search()
**/
node *insert_head(node*head)
{
node *New,*temp;
New = get_node();
printf (“\n Enter the element which you want to insert ”);
scanf(“%d”,&New->data);
if(head == NULL)
head = New;
else
{
temp=head;
New->next = temp;
head= New;
}
return head;
}
/*
*The get prev function
*Input: Address of starting node and the elemnt to be
*searched
*Output:looks for the element in the list
*If found returns pointer to the previous node otherwise NULL
*Parameter Passing Methods: call by value
*Called by : dele()
*Calls : none
**/
clrscr();
printf("\nENTER the Element you want to delete:");
scanf("%d".&key);
temp= search(*head,key);
if(temp !=NULL)
{
prev = get_prev(*head,key);
if(prev != NULL)
{
prev ->next = temp-> next;
free(temp);
}
else
{
*head = temp->next;
free(temp); // using the mem. Dellocation function
}
printf(“\n”The Element is deleted\n”);
getch();
clrscr();
}
}
Output:
Program to perform various operations on heap using Dynamic memory
management.
1. Create
2. Display
3. Insert an element in a list
4. Delete an element from list
5. Quit
Enter your choice(1-5) 1
1. Create
2. Display
3. Insert an element in a list
4. Delete an element from list
5. Quit
Enter your choice(1-5) 4
1. Create
2. Display
3. Insert an element in a list
4. Delete an element from list
5. Quit
Enter your choice(1-5) 2
10-> 30-> NULL
6. Generate Lexical analyzer using LEX.
%{
/*******************************************************************
Program to obtain tokens from a c program using LEX
<lexp.l>
*******************************************************************/
int COMMENT = 0;
int cnt = 0;
%}
identifier[a-zA-Z][a-zA-Z0-9]*
%%
int |
float |
char |
double |
while |
for |
do |
if |
break |
continue |
void |
switch |
switch |
case |
long |
struct |
const |
typedef |
return |
else |
goto {printf("\n\t%s is a KEYWORD",yytext);}
\} {if(!COMMENT)printf("\nBLOCK ENDS");}
{identifier}(\[0-9]*\])? {if(!COMMENT)printf("\n\t%s is an
IDENTIFIER",yytext);}
\)(\;)? {if(!COMMENT)printf("\n\t");ECHO;print("\n";)}
\( ECHO;
= {if(!COMMENT)printf("\n\t%s is an ASSIGNMENT OPERATOR",yytext)}
\+|
\- {if(!COMMENT)printf("\n\t%s is an OPERATOR",yytext);}
\<=|
\>=|
\<|
==|
\> {if(!COMMENT)printf(\n\t%s is a RELATIONAL OPERATOR",yytext);}
|\n
%%
int main(int argc.char**argv)
{
if(argc>1)
{
FILE *file';
file fopen(argv[1]."r");
if(file)
{
printf(“\n Could not open %s”,argv[1];
exit(0);
}
yyin = file;
}
yylex();
printf(“ \n Total number of comments are %d”,cnt);
return 0;
}
int yywrap()
{
return 1;
}
Input File:
#include<stdio.h>
#include<stdlib.h>
#include<stdio.h>
#include<stdlib.h>
double is a KEYWORD
area is an INDENTIFIER
of is an INDENTIFIER
circle is an INDENTIFIER
(double is a KEYWORD
r is an INDENTIFIER
);
int is a KEYWORD
main is an INDENTIFIER
(int is a KEYWORD
argc is an INDENTIFIER
char is a KEYWORD
argv[] is an INDENTIFIER
)
BLOCK BEGINS
if is a KEYWORD
(argc is an INDENTIFIER
< is a RELATIONAL OPERATOR
2 is a NUMBER
)
BLOCK BEGINS
printf is an INDENTIFIER
(“ Usage: %s radius \n”,is a STRING
argv[0] is an INDENTIFIER
);
exit is an INDENTIFIER
(1 is a NUMBER
);
BLOCK ENDS
else is a KEYWORD
BLOCK BEGINS
double is a KEYWORD
radius is an INDENTIFIER
= is an ASSIGNMENT OPERATOR
atof is an INDENTIFIER
(argv[1]is an INDENTIFIER
);
double is a KEYWORD
area is an INDENTIFIER
= is an ASSIGNMENT OPERATOR
area is an INDENTIFIER
of is an INDENTIFIER
circle is an INDENTIFIER
(radius is an INDENTIFIER
);
printf is an INDENTIFIER
(“Area of circle with radius %f = %f \n”, is a STRING
radius is an INDENTIFIER
area is an INDENTIFIER
);
BLOCK ENDS
return is a KEYWORD
0 is a NUMBER
BLOCK ENDS
Total number of comments are 3{root@localhost]#
7. Generate YACC specification for a few syntactic categories.
a) Program to recognize a valid arithmetic expression that uses
operator +, - , * and /.
Program name:arith_id.l
%{
/* This LEX program returns the tokens for the expression */
#include “y.tab.h”
%}
%%
“=” {printf(“\n Operator is EQUAL”);}
“+” {printf(“\n Operator is PLUS”);}
“-“ {printf(“\n Operator is MINUS”);}
“/” {printf(“\n Operator is DIVISION”);}
“*” {printf(“\n Operator is MULTIPLICATION”);}
[a-z A-Z]*[0-9]* {
printf(“\n Identifier is %s”,yytext);
return ID;
}
return yytext[0];
\n return 0;
%%
int yywrap()
{
return 1;
}
%{
#include<stdio.h>
/* This YYAC program is for recognizing the Expression */
%}
%%
statement: A’=’E
| E {
printf(“\n Valid arithmetic expression”);
$$ = $1;
};
E: E’+’ID
| E’-’ID
| E’*’ID
| E’/’ID
| ID
;
%%
extern FILE *yyin;
main()
{
do
{
yyparse();
}while(!feof(yyin));
}
yyerror(char*s)
{
}
Output:
[root@localhost]# lex arith_id.1
[root@localhost]# yacc –d arith_id.y
[root@localhost]# gcc lex.yy.c y.tab.c
[root@localhost]# ./a.out
x=a+b;
Identifier is x
Operator is EQUAL
Identifier is a
Operator is PLUS
Identifier is b
Output:
[root@localhost]# lex variable_test.I
[root@localhost]# yacc –d variable_test.y
[root@localhost]# gcc lex.yy.c y.tab.c
[root@localhost]# ./a.out
int a,b;
Identifier is a
Identifier is b[root@localhost]#
c) Program to recognise the gramar(anb where n>=10)
%{
/*Lex Program for anb(n>=10)*/
%}
%%
a {return A;}
b {return B;}
. {return yytext[10];}
\n return('\n');
%%
int yywrap()
{
return 1;
}
Program name:anb.y
%{
/*YACC program for recognising anb(n>=10)*/
%}
%token A B
%%
stmt:A A A A A A A A A A anb'\n'{printf("\n Valid string");
return 0;
}
;
anb:A anb
|A B
;
%%
main()
{
printf("\nEnter some valid string\n");
yyparse();
}
int yyerror(char*s)
{
printf("\nInvalid string\n");
}
Output:
[root@localhost]# lex anb.1
[root@localhost]# yacc -d anb.y
[root@localhost]# gcc lex.yy.c y.tab.c
[root@localhost]# ./a.out
Enter some valid string
aaaaaaaaab
Invalid string
[root@localhost]# ./a.out
Program name:calci.l
%{
#include "y.tab.h" /*defines the tokens*/
#include ,math.h.
%}
%%
/*To recognise a valid number*/
([0-9] + |([0-9]*\.[0-9]+)([eE][-+]?[0-9]+)?) {yylval.dval =
atof(yytext);
return NUMBER;}
/*For log no | Log no (log base 10)*/
log | LOG {return LOG;}
/*End of input*/
\$ {return 0;}
/*No associativity*/
%nonassoc UMINUS /*Unary Minus*/
Output:
2 * 2 + 5 / 4
Answer = 5.25
mem = cos 45
sin 45/mem
Answer = 1
ln 10
Answer = 2.30259
8. Given any intermediate code form implement code optimization
techniques.
/*******************************************************************
Program for Code Optimization Technique of Constant Folding
*******************************************************************/
#include<stdio.h>
#include<string.h>
#include<conio.h>
#include<stdlib.h>
#include<ctype.h>
struct ConstFold
(
char new_Str[10];
char str[10];
}Opt_Data[20];
int New_Index=0;
int main()
{
file *In_file,*Out_file;
char Buffer[100],ch;
int i=0;
In_file = fopen(“d:\\code.txt”,”r”);
Out_file = fopen(“d:\\output.txt”,”w”);
clrscr();
while(1)
{
Ch = fgetc(In_file);
i=0;
while(1)
{
If(ch == ‘\n’)
break;
Buffer[i++]=ch;
ch = fgetc(_file);
if(ch == EOF)
break;
}//End while
if(ch ==EOF)
break;
Buffer[i]=’\0’;
ReadInput(Bufer, Out_file);//writing to the output file
}//End while
return 0;
}//End main
void ReadInput(char Buffer[],FILE *Out_file)
{
char temp[100],Token[10][10];
int n,I,j,flag=0;
strcpy(temp,Buffer);
n= Gen_token(temp,Token);
for(i=0;i<n;i++)
{
if(!strcmp(Token[i],”=”))
{
if(isdigit(Token[i+1][0])||Token[i+1][0] == ’.’)
{
/*If yes then saving that number and its variable
In the Opt_Data array*/
flag=1;
strcpy(Opt_Data[New_Index].New_Str,Token[i-1]);
strcpy(Opt_Data[New_Index++].str,Token[i+1]);
}//End if
}//End if
}//End for
if(!flag)
{
for(i=0;i<New_index;i++)
{
for(j=0;j<n;j++)
{
if(!strcmp(Opt_Data[i].new_Str,Token[j]))
strcpy(Token[j],Opt_Data[i].str);
}//End for
}//End for
}//End if
fflush(Out_file);
strcpy(temp,””);
for(i=0;i<n;i++) /*Loop to obtain complete tokens*/
{
strcat(tem,Token[i]);
if(Token[i+1][0]!=’,’||Token[i+1][0] != ‘,’)
strcat(temp,” “);
}//End for
strcat(temp,”\n\0”);
fwrite(&temp,strlen(temp),1,Out_file);
}
main()
{
float pi=3.14,r,a;
a = pi*r*r;
printf(“a = %f”,a);
return 0;
}
#include"stdio.h"
#include<conio.h>
char array[10][20],temp[10];
int c,n;void fun(int,int[]);
int fun2(int i,int j,int p[],int key)
{
int k;
if(!key)
{
for(k=0;k<n;k++)
if(array[i][j]==array[k][0])
break;
p[0]=i;p[1]=j+1;
fun(k,p);
return 0;
}
else
{
for(k=0;k<=c;k++)
{
if(array[i][j]==temp[k])
break;
}
if(k>c)return 1;
else return 0;
}
}
void main()
{
int p[2],i,j;
clrscr();
printf("Enter the no. of productions :");
scanf("%d",&n);
printf("Enter the productions :\n");
for(i=0;i<n;i++)
scanf("%s",array[i]);
for(i=0;i<n;i++)
{
c=-1,p[0]=-1,p[1]=-1;
fun(i,p);
printf("First(%c) : [ ",array[i][0]);
for(j=0;j<=c;j++)
printf("%c,",temp[j]);
printf("\b ].\n");
getch();
}
}
Output:
#include"stdio.h"
#include<conio.h>
#define max 10
#define MAX 15
char array[max][MAX],temp[max][MAX];
int c,n,t;void fun(int,int[]);
void follow(int i)
{
int j,k;
for(j=0;j<=ff0;j++)
if(array[i][0]==ff[j])
return 0;
if(j>ff0)ff[++ff0]=array[i][0];
if(i==0)fol[l][++f]='$';
for(j=0;j<n;j++)
for(k=2;array[j][k]!='\0';k++)
if(array[j][k]==array[i][0])
ffun(j,k);
}
/* Follow Finding */
for(i=0,l=0;i<n;i++,l++)
{
f=-1;ff0=-1;
fol[l][++f]=array[i][0];
follow(i);
fol[l][++f]='\0';
}
for(i=0;i<n;i++)
{
printf("\nFollow[%c] : [ ",fol[i][0]);
for(j=1;fol[i][j]!='\0';j++)
printf("%c,",fol[i][j]);
printf("\b ]");
getch();
}
}
Output:
Enter the no. of productions :6
Enter the productions :
S/aBDh
B/cC
C/bC/@
D/E/F
E/g/@
F/f/@
First(S) : [ a ].
First(B) : [ c ].
First(C) : [ b,@ ].
First(D) : [ g,@,f ].
First(E) : [ g,@ ].
First(F) : [ f,@ ].
Follow[S] : [ $ ]
Follow[B] : [ g,f,h,$ ]
Follow[C] : [ g,f,h,$ ]
Follow[D] : [ h ]
Follow[E] : [ h ]
Follow[F] : [ h ]