Look this simple, and
very poor, sample..., it's is in C#
Code:
using System;
using System.IO;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace CPreProcessor
{
public struct define
{
public string defName { get; set; }
public string defValu { get; set; }
}
class PrePro
{
private string incDir = @"C:\cb\include\";
private List<define> lsHash = new List<define>();
//private StreamWriter sw;
public PrePro(string fName)
{
//var fAux = fName.Split('.')[0] + ".ppo";
//sw = new StreamWriter(fAux);
parse(fName);
}
private void parse(string fileName)
{
var lines = File.ReadAllLines(fileName);
foreach(var line in lines)
{
if (line.Trim().StartsWith("#include"))
{
var aux = line.Replace("#include", "").Trim();
if (aux[0] == '<')
parse(incDir + (aux.Remove(0, 1).Remove(aux.Length - 2, 1)));
else if (aux[0] == '"')
parse(aux.Remove(0, 1).Remove(aux.Length - 2, 1));
else
throw new Exception("Erro");
}
else if (line.Trim().StartsWith("#define"))
{
define def = new define();
bool findName = false;
for(int i=7;i<line.Length;i++)
{
if (line[i] == ' ')
continue;
if (findName == true)
{
def.defValu = line.Substring(i, line.Length - i);
break;
}
else
{
var temp = "";
for (int j = i; j < line.Length; j++)
{
if (line[j] == ' ')
{
def.defName = temp;
findName = true;
i = j; // mode the index to correctly local
break;
}
else
temp += line[j];
}
}
}
lsHash.Add(def);
}
else
{
for(int i=0;i<line.Length;)
{
if(line[i] == '"')
for(int j=i;j<line.Length;j++)
{
if (line[j] != '"')
{
Console.Write(line[j]);
i++;
}
else
{
Console.Write(line[j]); // just to print the "
i++;
break;
}
}
else if(Char.IsNumber(line[i]))
{
do
{
Console.Write(line[i]);
i++;
if (i >= line.Length)
{
break;
}
} while (Char.IsNumber(line[i]) || line[i] == '.');
}
else if(Char.IsLetter(line[i]) || line[i] == '_')
{
var aux = "";
do
{
aux += line[i];
i++;
if (i >= line.Length)
{
break;
}
} while (Char.IsLetterOrDigit(line[i]) || line[i] == '_');
var temp = lsHash.Where(k => k.defName == aux).Select(t => t);
if (temp.Count() > 0)
Console.Write(temp.First().defValu);
else
Console.Write(aux);
}
else
{
Console.Write(line[i]);
i++;
}
}
Console.Write('\n');
}
}
}
}
class Program
{
static void Main(string[] args)
{
new PrePro("main.c");
}
}
}
And the
main.c code is that:
Code:
#include <stdio.h>
#define PI 3.14159
void main()
{
int n; // comment
double sum = 0.0; /* comment */
size_t test = 10;
for (n = 1; n <= 10; n++) sum += PI / n;
printf("sum = %.1f\n", sum);
}
The pre-processed source code is that:
Code:
// stdio.h
typedef struct _FILE {
char* _ptr;
int _cnt;
char* _base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char* _tmpfname;
} FILE;
__declspec(import) FILE _iob[];
void perror(const char *s);
int printf(char *format, ...);
int fprintf(FILE *fp, char *format, ...);
int sprintf(char *str, char *format, ...);
int scanf(char *format, ...);
int sscanf(const char *str, const char *format, ...);
FILE *fopen(char *filename, char *mode);
int fclose(FILE *stream);
char *fgets(char *s, int n, FILE *stream);
int fread(void *buf, int size, int n, FILE *fp);
int fwrite(const void *buf, int size, int n, FILE *fp);
char *gets(char *s);
int getchar();
int putchar(int c);
int puts(const char *s);
int rename(const char *old, const char *new);
int ungetc(int c, FILE *fp);
void main()
{
int n; // comment
double sum = 0.0; /* comment */
int test = 10;
for (n = 1; n <= 10; n++) sum += 3.14159 / n;
printf("sum = %.1f\n", sum);
}
Btw, with this, u just need to make the lexical and parser... in the parser u can make a simple PASM generator... just for study... in parser u will check the tokens and verify the semantics...