E
Eric des Courtis
Hi Everyone,
Before I go into details I would like to thank Svillen Ranev my
professor for solving the "How to define, declare and call a function
returning function pointers of the same type?" question I had asked in
the context of my compilers class.
The problem is this:
a function foo
foo()
taking as parameter a char
foo(char)
returning a pointer
*foo(char)
to a function (of the same type)
(*foo(char))()
taking char
(*foo(char))(char)
returning a pointer
*(*foo(char))(char)
to a function
(*(*foo(char))(char))()
taking char
(*(*foo(char))(char))(char)
and so on.....
This goes on forever.
It can be solved by simply recursing once and stopping there.
Naturally this generates a warning and usually the C compiler will
assume a int return type for the last return type effectively breaking
the recursion. To void warnings heavy casting is required, technically
speaking the compiler only need to correctly resolve the first return
type in order to generate valid output code.
So how does one make a finite state machine using this?
Like this... (This source is also available on my home machine at
http://clockwork.no-ip.org/ericdevice3.c)
/* This is a sample of Eric's device (Finite Automaton
Implementation)
* Copyright (C) 2008 Eric des courtis
*
* This program is free software: you can redistribute it and/or
modify
* it under the terms of the GNU General Public License as published
by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/
#include <stdio.h>
#include <stdlib.h>
#define NOAS 0
#define ASWR 1
#define ASNR 2
#define EOS '\0'
#define CRLF '\n'
#define NO_TOKEN 0
#define HELLO_TOKEN 1
#define BOB_TOKEN 2
#define NUMBER_TOKEN 3
#define ERROR_TOKEN 4
/* For casting */
#define SFP(a) ((void *(*(*)(char))(char))a)
#define STP(a) ((void *(*(*(*)(char))(char))(char))a)
/* For definition and declaration */
#define SF(f,t,v) void *(*(*f(t v))(t))(t)
#define PSF(n,t) void *(*(*(*n)(t))(t))(t);
struct token{
int type;
} tok;
static int acceptstate = NOAS;
static SF(state0, char,);
static SF(state1, char,);
static SF(state2, char,);
static SF(state3, char,);
static SF(state4, char,);
static SF(state5, char,);
static SF(state6, char,);
static SF(state7, char,);
static SF(state8, char,);
static SF(state9, char,);
static SF(error_state, char,);
static PSF(state, char);
int main(void)
{
char c = 0;
static char *token_name[] = {
"NO TOKEN?",
"HELLO TOKEN",
"BOB TOKEN",
"NUMBER TOKEN",
"ERROR TOKEN"
};
printf("Eric's device Example Copyright (C) 2008 Eric des Courtis\n"
"This program comes with ABSOLUTELY NO WARRANTY.\n"
"This is free software, and you are welcome to redistribute it
\n"
"under certain conditions.\n");
tok.type = NO_TOKEN;
state = state0;
do{
do{
if(acceptstate != ASWR){
c = (char)getchar();
if(c == CRLF) continue;
}
state = STP(state(c));
}while(acceptstate == NOAS);
printf("%s found\n", token_name[tok.type]);
}while(c != EOS && c != EOF);
return 0;
}
static SF(state0, char, a)
{
acceptstate = NOAS;
switch(a){
case 'h':
return SFP(state1);
case 'b':
return SFP(state6);
}
if(a >= '0' && a <= '9')
return SFP(state9);
return SFP(error_state);
}
static SF(state1, char, a)
{
acceptstate = NOAS;
if(a == 'e')
return SFP(state2);
return SFP(error_state);
}
static SF(state2, char, a)
{
acceptstate = NOAS;
if(a == 'l')
return SFP(state3);
return SFP(error_state);
}
static SF(state3, char, a)
{
acceptstate = NOAS;
if(a == 'l')
return SFP(state4);
return SFP(error_state);
}
static SF(state4, char, a)
{
acceptstate = NOAS;
if(a == 'o')
return SFP(state5);
return SFP(error_state);
}
static SF(state5, char, a)
{
acceptstate = ASWR;
tok.type = HELLO_TOKEN;
return SFP(state0);
}
static SF(state6, char, a)
{
acceptstate = NOAS;
if(a == 'o')
return SFP(state7);
return SFP(error_state);
}
static SF(state7, char, a)
{
acceptstate = NOAS;
if(a == 'b')
return SFP(state8);
return SFP(error_state);
}
static SF(state8, char, a)
{
acceptstate = ASWR;
tok.type = BOB_TOKEN;
return SFP(state0);
}
static SF(state9, char, a)
{
acceptstate = NOAS;
if(a >= '0' && a <= '9')
return SFP(state9);
acceptstate = ASWR;
tok.type = NUMBER_TOKEN;
return SFP(state0);
}
static SF(error_state, char, a)
{
acceptstate = ASWR;
tok.type = ERROR_TOKEN;
return SFP(state0);
}
I decided to call this thing Eric's Device!
Cheers!
Eric des Courtis
Before I go into details I would like to thank Svillen Ranev my
professor for solving the "How to define, declare and call a function
returning function pointers of the same type?" question I had asked in
the context of my compilers class.
The problem is this:
a function foo
foo()
taking as parameter a char
foo(char)
returning a pointer
*foo(char)
to a function (of the same type)
(*foo(char))()
taking char
(*foo(char))(char)
returning a pointer
*(*foo(char))(char)
to a function
(*(*foo(char))(char))()
taking char
(*(*foo(char))(char))(char)
and so on.....
This goes on forever.
It can be solved by simply recursing once and stopping there.
Naturally this generates a warning and usually the C compiler will
assume a int return type for the last return type effectively breaking
the recursion. To void warnings heavy casting is required, technically
speaking the compiler only need to correctly resolve the first return
type in order to generate valid output code.
So how does one make a finite state machine using this?
Like this... (This source is also available on my home machine at
http://clockwork.no-ip.org/ericdevice3.c)
/* This is a sample of Eric's device (Finite Automaton
Implementation)
* Copyright (C) 2008 Eric des courtis
*
* This program is free software: you can redistribute it and/or
modify
* it under the terms of the GNU General Public License as published
by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/
*/
#include <stdio.h>
#include <stdlib.h>
#define NOAS 0
#define ASWR 1
#define ASNR 2
#define EOS '\0'
#define CRLF '\n'
#define NO_TOKEN 0
#define HELLO_TOKEN 1
#define BOB_TOKEN 2
#define NUMBER_TOKEN 3
#define ERROR_TOKEN 4
/* For casting */
#define SFP(a) ((void *(*(*)(char))(char))a)
#define STP(a) ((void *(*(*(*)(char))(char))(char))a)
/* For definition and declaration */
#define SF(f,t,v) void *(*(*f(t v))(t))(t)
#define PSF(n,t) void *(*(*(*n)(t))(t))(t);
struct token{
int type;
} tok;
static int acceptstate = NOAS;
static SF(state0, char,);
static SF(state1, char,);
static SF(state2, char,);
static SF(state3, char,);
static SF(state4, char,);
static SF(state5, char,);
static SF(state6, char,);
static SF(state7, char,);
static SF(state8, char,);
static SF(state9, char,);
static SF(error_state, char,);
static PSF(state, char);
int main(void)
{
char c = 0;
static char *token_name[] = {
"NO TOKEN?",
"HELLO TOKEN",
"BOB TOKEN",
"NUMBER TOKEN",
"ERROR TOKEN"
};
printf("Eric's device Example Copyright (C) 2008 Eric des Courtis\n"
"This program comes with ABSOLUTELY NO WARRANTY.\n"
"This is free software, and you are welcome to redistribute it
\n"
"under certain conditions.\n");
tok.type = NO_TOKEN;
state = state0;
do{
do{
if(acceptstate != ASWR){
c = (char)getchar();
if(c == CRLF) continue;
}
state = STP(state(c));
}while(acceptstate == NOAS);
printf("%s found\n", token_name[tok.type]);
}while(c != EOS && c != EOF);
return 0;
}
static SF(state0, char, a)
{
acceptstate = NOAS;
switch(a){
case 'h':
return SFP(state1);
case 'b':
return SFP(state6);
}
if(a >= '0' && a <= '9')
return SFP(state9);
return SFP(error_state);
}
static SF(state1, char, a)
{
acceptstate = NOAS;
if(a == 'e')
return SFP(state2);
return SFP(error_state);
}
static SF(state2, char, a)
{
acceptstate = NOAS;
if(a == 'l')
return SFP(state3);
return SFP(error_state);
}
static SF(state3, char, a)
{
acceptstate = NOAS;
if(a == 'l')
return SFP(state4);
return SFP(error_state);
}
static SF(state4, char, a)
{
acceptstate = NOAS;
if(a == 'o')
return SFP(state5);
return SFP(error_state);
}
static SF(state5, char, a)
{
acceptstate = ASWR;
tok.type = HELLO_TOKEN;
return SFP(state0);
}
static SF(state6, char, a)
{
acceptstate = NOAS;
if(a == 'o')
return SFP(state7);
return SFP(error_state);
}
static SF(state7, char, a)
{
acceptstate = NOAS;
if(a == 'b')
return SFP(state8);
return SFP(error_state);
}
static SF(state8, char, a)
{
acceptstate = ASWR;
tok.type = BOB_TOKEN;
return SFP(state0);
}
static SF(state9, char, a)
{
acceptstate = NOAS;
if(a >= '0' && a <= '9')
return SFP(state9);
acceptstate = ASWR;
tok.type = NUMBER_TOKEN;
return SFP(state0);
}
static SF(error_state, char, a)
{
acceptstate = ASWR;
tok.type = ERROR_TOKEN;
return SFP(state0);
}
I decided to call this thing Eric's Device!
Cheers!
Eric des Courtis