Initial commit of pre-existing sources.

This commit is contained in:
Lionel Sambuc
2010-10-21 20:58:03 +02:00
commit 0a443b14f8
24 changed files with 1490 additions and 0 deletions

7
.gitignore vendored Normal file
View File

@@ -0,0 +1,7 @@
.*
*~
*.o
build/
Euuuhh.xcodeproj/*
!.gitignore

79
Euuuhh.1 Executable file
View File

@@ -0,0 +1,79 @@
.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples.
.\"See Also:
.\"man mdoc.samples for a complete listing of options
.\"man mdoc for the short list of editing options
.\"/usr/share/misc/mdoc.template
.Dd 20.11.09 \" DATE
.Dt Euuuhh 1 \" Program name and manual section number
.Os Darwin
.Sh NAME \" Section Header - required - don't modify
.Nm Euuuhh,
.\" The following lines are read in generating the apropos(man -k) database. Use only key
.\" words here as the database is built based on the words here and in the .ND line.
.Nm Other_name_for_same_program(),
.Nm Yet another name for the same program.
.\" Use .Nm macro to designate other names for the documented program.
.Nd This line parsed for whatis database.
.Sh SYNOPSIS \" Section Header - required - don't modify
.Nm
.Op Fl abcd \" [-abcd]
.Op Fl a Ar path \" [-a path]
.Op Ar file \" [file]
.Op Ar \" [file ...]
.Ar arg0 \" Underlined argument - use .Ar anywhere to underline
arg2 ... \" Arguments
.Sh DESCRIPTION \" Section Header - required - don't modify
Use the .Nm macro to refer to your program throughout the man page like such:
.Nm
Underlining is accomplished with the .Ar macro like this:
.Ar underlined text .
.Pp \" Inserts a space
A list of items with descriptions:
.Bl -tag -width -indent \" Begins a tagged list
.It item a \" Each item preceded by .It macro
Description of item a
.It item b
Description of item b
.El \" Ends the list
.Pp
A list of flags and their descriptions:
.Bl -tag -width -indent \" Differs from above in tag removed
.It Fl a \"-a flag as a list item
Description of -a flag
.It Fl b
Description of -b flag
.El \" Ends the list
.Pp
.\" .Sh ENVIRONMENT \" May not be needed
.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1
.\" .It Ev ENV_VAR_1
.\" Description of ENV_VAR_1
.\" .It Ev ENV_VAR_2
.\" Description of ENV_VAR_2
.\" .El
.Sh FILES \" File used or created by the topic of the man page
.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact
.It Pa /usr/share/file_name
FILE_1 description
.It Pa /Users/joeuser/Library/really_long_file_name
FILE_2 description
.El \" Ends the list
.\" .Sh DIAGNOSTICS \" May not be needed
.\" .Bl -diag
.\" .It Diagnostic Tag
.\" Diagnostic informtion here.
.\" .It Diagnostic Tag
.\" Diagnostic informtion here.
.\" .El
.Sh SEE ALSO
.\" List links in ascending order by section, alphabetically within a section.
.\" Please do not reference files that do not exist without filing a bug report
.Xr a 1 ,
.Xr b 1 ,
.Xr c 1 ,
.Xr a 2 ,
.Xr b 2 ,
.Xr a 3 ,
.Xr b 3
.\" .Sh BUGS \" Document known, unremedied bugs
.\" .Sh HISTORY \" Document history if command behaves in a unique manner

236
Euuuhh.xcodeproj/project.pbxproj Executable file
View File

@@ -0,0 +1,236 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 45;
objects = {
/* Begin PBXBuildFile section */
8DD76FAC0486AB0100D96B5E /* main.c in Sources */ = {isa = PBXBuildFile; fileRef = 08FB7796FE84155DC02AAC07 /* main.c */; settings = {ATTRIBUTES = (); }; };
8DD76FB00486AB0100D96B5E /* Euuuhh.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = C6A0FF2C0290799A04C91782 /* Euuuhh.1 */; };
E7E4EDEF10C85B3700C0DFE7 /* tokenizer.c in Sources */ = {isa = PBXBuildFile; fileRef = E7E4EDEE10C85B3700C0DFE7 /* tokenizer.c */; };
E7E4EDFF10C85EA000C0DFE7 /* bf.c in Sources */ = {isa = PBXBuildFile; fileRef = E7E4EDFE10C85EA000C0DFE7 /* bf.c */; };
E7E4EE0210C85EB800C0DFE7 /* Heu.c in Sources */ = {isa = PBXBuildFile; fileRef = E7E4EE0110C85EB800C0DFE7 /* Heu.c */; };
E7E4EE0A10C86B8B00C0DFE7 /* interpreter.c in Sources */ = {isa = PBXBuildFile; fileRef = E7E4EE0910C86B8B00C0DFE7 /* interpreter.c */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
8DD76FAF0486AB0100D96B5E /* CopyFiles */ = {
isa = PBXCopyFilesBuildPhase;
buildActionMask = 8;
dstPath = /usr/share/man/man1/;
dstSubfolderSpec = 0;
files = (
8DD76FB00486AB0100D96B5E /* Euuuhh.1 in CopyFiles */,
);
runOnlyForDeploymentPostprocessing = 1;
};
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
08FB7796FE84155DC02AAC07 /* main.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = main.c; sourceTree = "<group>"; };
8DD76FB20486AB0100D96B5E /* bfi */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = bfi; sourceTree = BUILT_PRODUCTS_DIR; };
C6A0FF2C0290799A04C91782 /* Euuuhh.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = Euuuhh.1; sourceTree = "<group>"; };
E72D4F1A10B73EA500D51B36 /* colors.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = colors.h; sourceTree = "<group>"; };
E79ECE0610CE1CF700BE68DA /* tokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = tokenizer.h; sourceTree = "<group>"; };
E7E4EDEE10C85B3700C0DFE7 /* tokenizer.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tokenizer.c; sourceTree = "<group>"; };
E7E4EDFD10C85EA000C0DFE7 /* interpreter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = interpreter.h; sourceTree = "<group>"; };
E7E4EDFE10C85EA000C0DFE7 /* bf.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = bf.c; sourceTree = "<group>"; };
E7E4EE0010C85EB800C0DFE7 /* Heu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Heu.h; sourceTree = "<group>"; };
E7E4EE0110C85EB800C0DFE7 /* Heu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = Heu.c; sourceTree = "<group>"; };
E7E4EE0310C85F0400C0DFE7 /* bf.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bf.h; sourceTree = "<group>"; };
E7E4EE0910C86B8B00C0DFE7 /* interpreter.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = interpreter.c; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
8DD76FAD0486AB0100D96B5E /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
08FB7794FE84155DC02AAC07 /* Euuuhh */ = {
isa = PBXGroup;
children = (
08FB7795FE84155DC02AAC07 /* Source */,
C6A0FF2B0290797F04C91782 /* Documentation */,
1AB674ADFE9D54B511CA2CBB /* Products */,
);
name = Euuuhh;
sourceTree = "<group>";
};
08FB7795FE84155DC02AAC07 /* Source */ = {
isa = PBXGroup;
children = (
E79ECE0610CE1CF700BE68DA /* tokenizer.h */,
E7E4EDEE10C85B3700C0DFE7 /* tokenizer.c */,
E72D4F1A10B73EA500D51B36 /* colors.h */,
08FB7796FE84155DC02AAC07 /* main.c */,
E7E4EDFD10C85EA000C0DFE7 /* interpreter.h */,
E7E4EE0910C86B8B00C0DFE7 /* interpreter.c */,
E7E4EE0310C85F0400C0DFE7 /* bf.h */,
E7E4EDFE10C85EA000C0DFE7 /* bf.c */,
E7E4EE0010C85EB800C0DFE7 /* Heu.h */,
E7E4EE0110C85EB800C0DFE7 /* Heu.c */,
);
name = Source;
sourceTree = "<group>";
};
1AB674ADFE9D54B511CA2CBB /* Products */ = {
isa = PBXGroup;
children = (
8DD76FB20486AB0100D96B5E /* bfi */,
);
name = Products;
sourceTree = "<group>";
};
C6A0FF2B0290797F04C91782 /* Documentation */ = {
isa = PBXGroup;
children = (
C6A0FF2C0290799A04C91782 /* Euuuhh.1 */,
);
name = Documentation;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
8DD76FA90486AB0100D96B5E /* bfi */ = {
isa = PBXNativeTarget;
buildConfigurationList = 1DEB928508733DD80010E9CD /* Build configuration list for PBXNativeTarget "bfi" */;
buildPhases = (
8DD76FAB0486AB0100D96B5E /* Sources */,
8DD76FAD0486AB0100D96B5E /* Frameworks */,
8DD76FAF0486AB0100D96B5E /* CopyFiles */,
);
buildRules = (
);
dependencies = (
);
name = bfi;
productInstallPath = "$(HOME)/bin";
productName = Euuuhh;
productReference = 8DD76FB20486AB0100D96B5E /* bfi */;
productType = "com.apple.product-type.tool";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
08FB7793FE84155DC02AAC07 /* Project object */ = {
isa = PBXProject;
buildConfigurationList = 1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "Euuuhh" */;
compatibilityVersion = "Xcode 3.1";
developmentRegion = English;
hasScannedForEncodings = 1;
knownRegions = (
English,
Japanese,
French,
German,
);
mainGroup = 08FB7794FE84155DC02AAC07 /* Euuuhh */;
projectDirPath = "";
projectRoot = "";
targets = (
8DD76FA90486AB0100D96B5E /* bfi */,
);
};
/* End PBXProject section */
/* Begin PBXSourcesBuildPhase section */
8DD76FAB0486AB0100D96B5E /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8DD76FAC0486AB0100D96B5E /* main.c in Sources */,
E7E4EDEF10C85B3700C0DFE7 /* tokenizer.c in Sources */,
E7E4EDFF10C85EA000C0DFE7 /* bf.c in Sources */,
E7E4EE0210C85EB800C0DFE7 /* Heu.c in Sources */,
E7E4EE0A10C86B8B00C0DFE7 /* interpreter.c in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin XCBuildConfiguration section */
1DEB928608733DD80010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
COPY_PHASE_STRIP = NO;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_FIX_AND_CONTINUE = YES;
GCC_MODEL_TUNING = G5;
GCC_OPTIMIZATION_LEVEL = 0;
INSTALL_PATH = /usr/local/bin;
PRODUCT_NAME = bfi;
};
name = Debug;
};
1DEB928708733DD80010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
GCC_MODEL_TUNING = G5;
INSTALL_PATH = /usr/local/bin;
PRODUCT_NAME = bfi;
};
name = Release;
};
1DEB928A08733DD80010E9CD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(NATIVE_ARCH)";
GCC_C_LANGUAGE_STANDARD = c99;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
ONLY_ACTIVE_ARCH = YES;
PREBINDING = NO;
SDKROOT = macosx10.5;
};
name = Debug;
};
1DEB928B08733DD80010E9CD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ARCHS = "$(NATIVE_ARCH)";
GCC_C_LANGUAGE_STANDARD = c99;
GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
PREBINDING = NO;
SDKROOT = macosx10.5;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
1DEB928508733DD80010E9CD /* Build configuration list for PBXNativeTarget "bfi" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB928608733DD80010E9CD /* Debug */,
1DEB928708733DD80010E9CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
1DEB928908733DD80010E9CD /* Build configuration list for PBXProject "Euuuhh" */ = {
isa = XCConfigurationList;
buildConfigurations = (
1DEB928A08733DD80010E9CD /* Debug */,
1DEB928B08733DD80010E9CD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 08FB7793FE84155DC02AAC07 /* Project object */;
}

160
Heu.c Executable file
View File

@@ -0,0 +1,160 @@
/*
* Created by Lionel Sambuc on 03.dec.2009.
* Copyright 2009. All rights reserved.
*
*/
#include <stdio.h>
#include <string.h>
#include "interpreter.h"
#include "tokenizer.h"
#include "Heu.h"
static char *heu[NB_KWS];
/**************************************************************************
* PRIVATE INTERFACE *
**************************************************************************/
/**
* Heu separator detector.
*/
int heu_is_separator(char c)
{
return !(c == 'H');
}
/**
* Read a token from the program stream, in the given direction.
* Parameters :
* * direction positive : go from the left to the right
* negative : go from the right to the left
* zero : invalid direction.
* * program the program from which to read a token
* * token_start the actual position within the program
* * length the length of the program
*/
static int read_token(int direction, char const *program, int *token_start, size_t length)
{
size_t token_length, keyword_length;
char const *token;
/* Check that we have a sane direction. */
if(direction == 0)
return UKW;
/* Read the next token. */
if(direction > 0)
{
/* Try to find the next token. */
if(!tk_next_token(program, token_start, &token_length))
return EOT; /* It was not found. */
/* Save the token to be analyzed. */
token = program + *token_start;
/* We are updating the token_start position later as we have variable
* length tokens.
*/
}
/* Read the previous token. */
if(direction < 0)
{
--*token_start;
/* Try to find the previous token. */
if(!tk_previous_token(program, token_start, &token_length))
return SOT;/* It was not found. */
/* Save the token to be analyzed. */
token = program + *token_start;
}
/* Match the token characters to a known token value.
* also update token_start as well. */
if(*token_start + (keyword_length = strlen(heu[MVL])) <= length &&
strncmp(heu[MVL], token, keyword_length) == 0)
{
*token_start += (direction > 0) ? keyword_length : -1;
return MVL;
}
if(*token_start + (keyword_length = strlen(heu[MVR])) <= length &&
strncmp(heu[MVR], token, keyword_length) == 0)
{
*token_start += (direction > 0) ? keyword_length : -1;
return MVR;
}
if(*token_start + (keyword_length = strlen(heu[INC])) <= length &&
strncmp(heu[INC], token, keyword_length) == 0)
{
*token_start += (direction > 0) ? keyword_length : -1;
return INC;
}
if(*token_start + (keyword_length = strlen(heu[DEC])) <= length &&
strncmp(heu[DEC], token, keyword_length) == 0)
{
*token_start += (direction > 0) ? keyword_length : -1;
return DEC;
}
if(*token_start + (keyword_length = strlen(heu[PUT])) <= length &&
strncmp(heu[PUT], token, keyword_length) == 0)
{
*token_start += (direction > 0) ? keyword_length : -1;
return PUT;
}
if(*token_start + (keyword_length = strlen(heu[GET])) <= length &&
strncmp(heu[GET], token, keyword_length) == 0)
{
*token_start += (direction > 0) ? keyword_length : -1;
return GET;
}
if(*token_start + (keyword_length = strlen(heu[JZF])) <= length &&
strncmp(heu[JZF], token, keyword_length) == 0)
{
*token_start += (direction > 0) ? keyword_length : -1;
return JZF;
}
if(*token_start + (keyword_length = strlen(heu[JNB])) <= length &&
strncmp(heu[JNB], token, keyword_length) == 0)
{
*token_start += (direction > 0) ? keyword_length : -1;
return JNB;
}
return UKW;
}
/**************************************************************************
* PUBLIC INTERFACE *
**************************************************************************/
void heu_lexer_init()
{
heu[MVR] = "Heu !";
heu[MVL] = "Heu ?";
heu[INC] = "Heu...";
heu[DEC] = "Heu.";
heu[PUT] = "Heu, j'avais pensé que.";
heu[GET] = "Heu, t'en penses quoi ?";
heu[JZF] = "Heu, heu!";
heu[JNB] = "Heu, heu?";
tk_is_separator = heu_is_separator;
}
int heu_read_next_token(char const *program, int *token_start, size_t length)
{
return read_token(+1, program, token_start, length);
}
int heu_read_previous_token(char const *program, int *token_start, size_t length)
{
return read_token(-1, program, token_start, length);
}

58
Heu.h Executable file
View File

@@ -0,0 +1,58 @@
/*
* Created by Lionel Sambuc on 03.dec.2009.
* Copyright 2009. All rights reserved.
*
*/
/**************************************************************************
* Heu lexer interface *
**************************************************************************/
#ifndef _HEU_H_
#define _HEU_H_
/**
* The Heu language is an isomorphism of the brainfuck language with the
* following associations :
*
* Language operator définition :
* ******************************
* > Heu!
* < Heu?
* + Heu...
* - Heu.
* . Heu, j'avais pensé que.
* , Heu, t'en penses quoi ?
* [ Heu, heu!
* ] Heu, heu?
*/
/**
* Initialize the Heu lexer.
*/
void heu_lexer_init();
/**
* Read the previous token found starting from the token_start position in
* program.
* Parameters :
* * program the program to tokenize.
* * token_start the position in the program from which to begin the search
* of the previous token, this value is update to point
* on the last character of the returned token.
* * length the total length of the program.
*/
int heu_read_previous_token(char const *program, int *token_start, size_t length);
/**
* Read the next token found starting from the token_start position in
* program.
* Parameters :
* * program the program to tokenize.
* * token_start the position in the program from which to begin the search
* of the next token, this value is updated to point after
* the last character of returned token.
* * length the total length of the program.
*/
int heu_read_next_token(char const *program, int *token_start, size_t length);
#endif /* _HEU_H_ */

140
bf.c Executable file
View File

@@ -0,0 +1,140 @@
/*
* Created by Lionel Sambuc on 03.dec.2009.
* Copyright 2009. All rights reserved.
*
*/
/**************************************************************************
* Brainfuck lexer *
**************************************************************************/
#include <string.h>
#include "interpreter.h"
#include "tokenizer.h"
#include "bf.h"
static char bf[NB_KWS];
/**************************************************************************
* PRIVATE INTERFACE *
**************************************************************************/
/**
* Brainfuck separator detector.
* Simply check whether the given character is one of the 8 reserved
* characters, if not it is a separator.
*/
static int brainfuck_is_separator(char c)
{
return !(c == '<' || c == '>' ||
c == '+' || c == '-' ||
c == '.' || c == ',' ||
c == '[' || c == ']');
}
/**
* Read a token from the program stream, in the given direction.
* Parameters :
* * direction positive : go from the left to the right
* negative : go from the right to the left
* zero : invalid direction.
* * program the program from which to read a token
* * token_start the actual position within the program
* * length the length of the program
*/
static int read_token(int direction, char const *program, int *token_start, size_t length)
{
char token;
size_t token_length;
/* Check that we have a sane direction. */
if(direction == 0)
return UKW;
/* Read the next token. */
if(direction > 0)
{
/* Try to find the next token. */
if(!tk_next_token(program, token_start, &token_length))
return EOT; /* It was not found. */
/* Save the token to be analyzed. */
token = *(program + *token_start);
/* Update the pointer to be __after__ the token we are analyzing.
* A simple increment does the job as we have only one character tokens.
*/
(*token_start)++;
}
/* Read the previous token. */
if(direction < 0)
{
/* Update the pointer to be __on the last character__ of the token we
* are analyzing. A simple decrement does the job as we have only one
* character tokens.
*/
(*token_start)--;
/* Try to find the previous token. */
if(!tk_previous_token(program, token_start, &token_length))
return SOT;/* It was not found. */
/* Save the token to be analyzed. */
token = *(program + *token_start);
}
/* Match the token characters to a known token value. */
if(bf[MVL] == token)
return MVL;
if(bf[MVR] == token)
return MVR;
if(bf[INC] == token)
return INC;
if(bf[DEC] == token)
return DEC;
if(bf[PUT] == token)
return PUT;
if(bf[GET] == token)
return GET;
if(bf[JZF] == token)
return JZF;
if(bf[JNB] == token)
return JNB;
return UKW;
}
/**************************************************************************
* PUBLIC INTERFACE *
**************************************************************************/
void brainfuck_lexer_init()
{
bf[MVR] = '>';
bf[MVL] = '<';
bf[INC] = '+';
bf[DEC] = '-';
bf[PUT] = '.';
bf[GET] = ',';
bf[JZF] = '[';
bf[JNB] = ']';
tk_is_separator = brainfuck_is_separator;
}
int brainfuck_read_next_token(char const *program, int *token_start, size_t length)
{
return read_token(+1, program, token_start, length);
}
int brainfuck_read_previous_token(char const *program, int *token_start, size_t length)
{
return read_token(-1, program, token_start, length);
}

70
bf.h Executable file
View File

@@ -0,0 +1,70 @@
/*
* Created by Lionel Sambuc on 03.dec.2009.
* Copyright 2009. All rights reserved.
*
*/
/**************************************************************************
* Brainfuck lexer interface *
**************************************************************************/
#ifndef _BF_H_
#define _BF_H_
/**
* The following as been taken from :
* http://en.wikipedia.org/wiki/Brainfuck#Language_design
*
* Some more information about the language and it's features:
* http://www.muppetlabs.com/~breadbox/bf/standards.html
*
* For some example you may go to :
* http://en.wikipedia.org/wiki/Brainfuck#Trivial
* http://esoteric.sange.fi/brainfuck/bf-source/prog/
*
* Language operator définition :
* ******************************
* > increment the data pointer (to point to the next cell to the right).
* < decrement the data pointer (to point to the next cell to the left).
* + increment (increase by one) the byte at the data pointer.
* - decrement (decrease by one) the byte at the data pointer.
* . output the value of the byte at the data pointer.
* , accept one byte of input, storing its value in the byte at the data
* pointer.
* [ if the byte at the data pointer is zero, then instead of moving the
* instruction pointer forward to the next command, jump it forward to
* the command after the matching ] command*.
* ] if the byte at the data pointer is nonzero, then instead of moving the
* instruction pointer forward to the next command, jump it back to the
* command after the matching [ command*.
*/
/**
* Initialize the brainfuck lexer.
*/
void brainfuck_lexer_init();
/**
* Read the previous token found starting from the token_start position in
* program.
* Parameters :
* * program the program to tokenize.
* * token_start the position in the program from which to begin the search
* of the previous token, this value is update to point
* on the last character of the returned token.
* * length the total length of the program.
*/
int brainfuck_read_previous_token(char const *program, int *token_start, size_t length);
/**
* Read the next token found starting from the token_start position in
* program.
* Parameters :
* * program the program to tokenize.
* * token_start the position in the program from which to begin the search
* of the next token, this value is updated to point after
* the last character of returned token.
* * length the total length of the program.
*/
int brainfuck_read_next_token(char const *program, int *token_start, size_t length);
#endif /* _BF_H_ */

1
bfi Symbolic link
View File

@@ -0,0 +1 @@
build/Debug/bfi

42
colors.h Executable file
View File

@@ -0,0 +1,42 @@
#ifndef __COLORS_H__
#define __COLORS_H__
/**
* This macro permits to create the terminal code to modify the terminal font
* and background color, as well as the font style (normal, bold, underline).
*
* @param style The font style to apply, may be one of
* { NORMAL, BOLD, UNDERLINE }
* @param fg The font foreground color to apply, may be one of
* { BLACK, RED, GREEN, YELLOW, BLUE, VIOLET, CYAN, WHITE }
* @param bg The font background color to apply, may be one of
* { BLACK, RED, GREEN, YELLOW, BLUE, VIOLET, CYAN, WHITE }
*
* Authors: Lionel Sambuc
* Copyright: © 2010 Lionel Sambuc. All rights reserved.
*/
#define _CREATE_COLOR(style, fg, bg) \
"\033[" #style ";3" #fg ";4" #bg "m"
/* This step is needed to ensure proper replacement of the constant names to
* their values. */
#define CREATE_COLOR(style, fg, bg) _CREATE_COLOR(style, fg, bg)
/* Reset to standard colors */
#define DEFAULT_COLOR 8
/* Font Styles */
#define NORMAL 0
#define BOLD 1
#define UNDERLINE 4
/* Colors */
#define BLACK 0
#define RED 1
#define GREEN 2
#define YELLOW 3
#define BLUE 4
#define VIOLET 5
#define CYAN 6
#define WHITE 7
#endif /* __COLORS_H__ */

13
examples/2468-commented.bf Executable file
View File

@@ -0,0 +1,13 @@
This brainfuck program prints the following
suits on the screen : 2468
++++ the number of number to print
[
> Move to the accumulator cell
++ Add two to the accumulator
which leads to the multiplication
of the loop counter
. Print the accumulator
<- move back to the loop counter and
decrement it
]

13
examples/2468-commented.heu Executable file
View File

@@ -0,0 +1,13 @@
This brainfuck program prints the following
suits on the screen : 2468
Heu...Heu...Heu...Heu... the number of number to print
Heu, heu!
Heu ! Move to the accumulator cell
Heu...Heu... Add two to the accumulator
which leads to the multiplication
of the loop counter
Heu, j'avais pensé que. Print the accumulator
Heu ?Heu. move back to the loop counter and
decrement it
Heu, heu?

1
examples/2468.bf Executable file
View File

@@ -0,0 +1 @@
++++[>++.<-]

1
examples/2468.heu Executable file
View File

@@ -0,0 +1 @@
Heu...Heu...Heu...Heu...Heu, heu!Heu !Heu...Heu...Heu, j'avais pensé que.Heu ?Heu.Heu, heu?

View File

@@ -0,0 +1,21 @@
+++ +++ +++ + initialize counter (cell #0) to 10
[ use loop to set the next four cells to 70/100/30/10
> +++ +++ + add 7 to cell #1
> +++ +++ +++ + add 10 to cell #2
> +++ add 3 to cell #3
> + add 1 to cell #4
<<< < - decrement counter (cell #0)
]
>++ . print 'H'
>+. print 'e'
+++ +++ +. print 'l'
. print 'l'
+++ . print 'o'
>++ . print ' '
<<+ +++ +++ +++ +++ ++. print 'W'
>. print 'o'
+++ . print 'r'
--- --- . print 'l'
--- --- --. print 'd'
>+. print '!'
>. print '\n'

View File

@@ -0,0 +1,27 @@
Heu...Heu...Heu... Heu...Heu...Heu... Heu...Heu...Heu... Heu... initialize counter (cell #0) to 10
Heu, heu! use loop to set the next four cells to 70/100/30/10
Heu ! Heu...Heu...Heu... Heu...Heu...Heu... Heu... add 7 to cell #1
Heu ! Heu...Heu...Heu... Heu...Heu...Heu... Heu...Heu...Heu... Heu... add 10 to cell #2
Heu ! Heu...Heu...Heu... add 3 to cell #3
Heu ! Heu... add 1 to cell #4
Heu ?Heu ?Heu ? Heu ? Heu. decrement counter (cell #0)
Heu, heu?
Heu !Heu...Heu... Heu, j'avais pensé que. print 'H'
Heu !Heu...Heu, j'avais pensé que. print 'e'
Heu...Heu...Heu... Heu...Heu...Heu... Heu...Heu, j'avais pensé que. print 'l'
Heu, j'avais pensé que. print 'l'
Heu...Heu...Heu... Heu, j'avais pensé que. print 'o'
Heu !Heu...Heu... Heu, j'avais pensé que. print ' '
Heu ?Heu ?Heu...
Heu...Heu...Heu...
Heu...Heu...Heu...
Heu...Heu...Heu...
Heu...Heu...Heu...
Heu...Heu...Heu, j'avais pensé que. print 'W'
Heu !Heu, j'avais pensé que. print 'o'
Heu...Heu...Heu... Heu, j'avais pensé que. print 'r'
Heu.Heu.Heu. Heu.Heu.Heu. Heu, j'avais pensé que. print 'l'
Heu.Heu.Heu. Heu.Heu.Heu. Heu.Heu.Heu, j'avais pensé que. print 'd'
Heu !Heu...Heu, j'avais pensé que. print '!'
Heu !Heu, j'avais pensé que. print '\n'

3
examples/HelloWorld.bf Executable file
View File

@@ -0,0 +1,3 @@
++++++++[>+++++++++<-]>.<+++++[>++++++<-]>-.+++++++..+++.<
++++++++[>>++++<<-]>>.<<++++[>------<-]>.<++++[>++++++<-]>
.+++.------.--------.>+.

1
examples/HelloWorld.heu Executable file
View File

@@ -0,0 +1 @@
Heu...Heu...Heu...Heu...Heu...Heu...Heu...Heu...Heu, heu!Heu !Heu...Heu...Heu...Heu...Heu...Heu...Heu...Heu...Heu...Heu ?Heu.Heu, heu?Heu !Heu, j'avais pensé que.Heu ?Heu...Heu...Heu...Heu...Heu...Heu, heu!Heu !Heu...Heu...Heu...Heu...Heu...Heu...Heu ?Heu.Heu, heu?Heu !Heu.Heu, j'avais pensé que.Heu...Heu...Heu...Heu...Heu...Heu...Heu...Heu, j'avais pensé que.Heu, j'avais pensé que.Heu...Heu...Heu...Heu, j'avais pensé que.Heu ?Heu...Heu...Heu...Heu...Heu...Heu...Heu...Heu...Heu, heu!Heu !Heu !Heu...Heu...Heu...Heu...Heu ?Heu ?Heu.Heu, heu?Heu !Heu !Heu, j'avais pensé que.Heu ?Heu ?Heu...Heu...Heu...Heu...Heu, heu!Heu !Heu.Heu.Heu.Heu.Heu.Heu.Heu ?Heu.Heu, heu?Heu !Heu, j'avais pensé que.Heu ?Heu...Heu...Heu...Heu...Heu, heu!Heu !Heu...Heu...Heu...Heu...Heu...Heu...Heu ?Heu.Heu, heu?Heu !Heu, j'avais pensé que.Heu...Heu...Heu...Heu, j'avais pensé que.Heu.Heu.Heu.Heu.Heu.Heu.Heu, j'avais pensé que.Heu.Heu.Heu.Heu.Heu.Heu.Heu.Heu.Heu, j'avais pensé que.Heu !Heu...Heu, j'avais pensé que.

1
examples/test.heu Executable file
View File

@@ -0,0 +1 @@
Heu...Heu...Heu...Heu...Heu, heu!Heu !Heu...Heu...Heu ?Heu.Heu, heu?

15
examples/translate.pl Executable file
View File

@@ -0,0 +1,15 @@
#!/usr/bin/perl
# ./translate.pl "brainfuck program" > program.heu
{
$ARGV[0] =~ s/>/Heu !/g;
$ARGV[0] =~ s/</Heu ?/g;
#Beware the following replacement contains characters of the source set
$ARGV[0] =~ s/,/Heu, t'en penses quoi ?/g;
$ARGV[0] =~ s/\./Heu, j'avais pensé que./g;
$ARGV[0] =~ s/\+/Heu.../g;
$ARGV[0] =~ s/-/Heu./g;
$ARGV[0] =~ s/\[/Heu, heu!/g;
$ARGV[0] =~ s/\]/Heu, heu?/g;
print $ARGV[0];
}

221
interpreter.c Executable file
View File

@@ -0,0 +1,221 @@
/*
* Created by Lionel Sambuc on 03.dec.2009.
* Copyright 2009. All rights reserved.
*
*/
/**************************************************************************
* Brainfuck and derivatives interpreter *
**************************************************************************/
#include <stdio.h>
#include "bf.h"
#include "Heu.h"
#include "interpreter.h"
/* Program Input */
static char *bfi_program;
static int bfi_token_start;
static size_t bfi_length;
/* Program tokenizer functions */
static int (*bfi_read_previous_token)(char const *program, int *token_start, size_t length);
static int (*bfi_read_next_token)(char const *program, int *token_start, size_t length);
static void (*bfi_lexer_init)(void);
/* Machine hardware */
static char bfi_memory[NB_MEMORY_WORDS];
/* Reading/Writing Head, which points to a memory word */
static char *bfi_head;
/**************************************************************************
* PRIVATE INTERFACE *
**************************************************************************/
/**
* Prints the error message and dump the interpreter memory before returning
* the given error code.
*/
static int bfi_execution_error(char* reason, int code)
{
int i;
printf( COLOR_RST "\n" COLOR_ERR "%s" COLOR_MSG "\n", reason);
printf( COLOR_RST "At position : %s" COLOR_MSG "\n", (bfi_program + bfi_token_start));
for(i = 0; i < MEMORY_DUMP_SIZE; i++)
printf("%s%02x", i%4==0? (i%16==0?"\n": "::"): " ", bfi_memory[i]);
printf(COLOR_RST "\n");
return code;
}
/**
* Jump to the associated closing bracket and returns the next instruction
* to be executed.
* Hypotheses: bfi_token_start points just after the opening bracket.
*/
static int bfi_skip_forward(void)
{
int context = 0;
int next = -1;
while((next = bfi_read_next_token(bfi_program, &bfi_token_start, bfi_length)) != EOT)
{
switch(next)
{ /* Opening bracket */
case JZF: context++;
break;
/* Closing bracket */
case JNB: context--;
if(context == 0)
return next;
break;
/* End of the program or unknown instruction. */
case EOT:
case SOT:
case UKW:
return next;
}
}
return next;
}
/**
* Jump to the associated opening bracket and returns the next instruction
* to be executed.
* Hypotheses: bfi_token_start points just before the closing bracket.
*/
int bfi_skip_backward(void)
{
int context = 0;
int prev = -1;
while((prev = bfi_read_previous_token(bfi_program, &bfi_token_start, bfi_length)) != SOT)
{
switch(prev)
{ /* Opening bracket */
case JZF: context--;
if(context == 0)
return prev;
break;
/* Closing bracket */
case JNB: context++;
break;
/* End of the program or unknown instruction. */
case EOT:
case SOT:
case UKW:
return prev;
}
}
return prev;
}
/**
* This function initializes the lexer associated to the given brainfuck
* dialect. It also zero the whole memory band and reset the head to the
* first word.
* it returns 0 on success or -1 if the dialect is unknown.
*/
static int bfi_initialize(enum bfi_dialects dialect)
{
int i;
/* Reset memory state. */
for(i = 0; i < NB_MEMORY_WORDS; i++)
bfi_memory[i] = 0;
bfi_head = bfi_memory;
/* Initialize the parser functions. */
switch(dialect)
{
case BRAINFUCK:
bfi_lexer_init = brainfuck_lexer_init;
bfi_read_previous_token = brainfuck_read_previous_token;
bfi_read_next_token = brainfuck_read_next_token;
break;
case HEU:
bfi_lexer_init = heu_lexer_init;
bfi_read_previous_token = heu_read_previous_token;
bfi_read_next_token = heu_read_next_token;
break;
default:
return -1;
break;
}
/* Initialize the chosen lexer. */
bfi_lexer_init();
return 0;
}
/**************************************************************************
* PUBLIC INTERFACE *
**************************************************************************/
int bfi_execute(char* program, size_t length, enum bfi_dialects dialect, char print_num)
{
int next = EOT;
bfi_program = program;
bfi_length = length;
if(bfi_initialize(dialect) != 0)
return -UNKNOWN_DIALECT;
while((next = bfi_read_next_token(bfi_program, &bfi_token_start, bfi_length)) != EOT && next != SOT)
{
switch(next)
{
case MVL:
--bfi_head;
if(bfi_head < bfi_memory)
return bfi_execution_error("HEAD Got past the start of memory!", -INVALID_MEMORY_ADDRESS);
break;
case MVR:
++bfi_head;
if(bfi_head >= bfi_memory + NB_MEMORY_WORDS)
return bfi_execution_error("HEAD Got past the end of memory!", -INVALID_MEMORY_ADDRESS);
break;
case INC:
++*bfi_head;
break;
case DEC:
--*bfi_head;
break;
case PUT:
if(print_num != 0)
printf("%i", *bfi_head);
else
putchar(*bfi_head);
break;
case GET:
*bfi_head = getchar();
break;
case JZF:
if(*bfi_head == 0)
next = bfi_skip_forward();
break;
case JNB:
if(*bfi_head != 0)
next = bfi_skip_backward();
break;
case UKW:
default:
return bfi_execution_error("Unknown keyword !", -INVALID_OPERATION);
}
}
bfi_execution_error("End of Program", *bfi_head);
/* Ensure there is an end of line */
printf("\n");
return (int)*bfi_head;
}

78
interpreter.h Executable file
View File

@@ -0,0 +1,78 @@
/*
* Created by Lionel Sambuc on 03.dec.2009.
* Copyright 2009. All rights reserved.
*
*/
/**************************************************************************
* Brainfuck and derivatives interpreter interface *
**************************************************************************/
#ifndef _INTERPRETOR_H_
#define _INTERPRETOR_H_
#include <stddef.h>
#include "colors.h"
/* The 8 Brainfuck operations */
#define NB_KWS 8
#define MVL 0 /* Move Left */
#define MVR 1 /* Move Right */
#define INC 2 /* Increment Value */
#define DEC 3 /* Decrement Value */
#define PUT 4 /* Putchar */
#define GET 5 /* Getchar */
#define JZF 6 /* Jump if Zero Forward */
#define JNB 7 /* Jump if Non zero Backward */
#define EOT -1 /* End of Text */
#define SOT -2 /* Start of Text */
#define UKW -3 /* Unknown keyword */
/* Machine hardware */
#define NB_MEMORY_WORDS 30000
#define MEMORY_DUMP_SIZE 64
/* Execution error codes (beware! must be outside the memory word value
* domain, i.e outside the range 0-255 at the moment) */
#define UNKNOWN_DIALECT 512
#define INVALID_MEMORY_ADDRESS 513
#define INVALID_OPERATION 514
enum bfi_dialects {BRAINFUCK, HEU};
/**
* Main parser function.
*
* Reset the turing machine state and immediatly begin the execution of the
* given program.
* On success interpretation the value of the currently selected memory word
* is returned (which is a value between 0 and 255).
* Parameters:
* * program the program to execute
* * length the total length of the program
* * dialect the specific brainfuck dialect of the program
* * print_num if 0 print the value of the memory cell as a character,
* otherwise print as a number.
*
* It may return the following error code :
* * -INVALID_MEMORY_ADDRESS when the interpreted program tries to go beyond
* the limits of the band.
* * -UNKNOWN_DIALECT when the given dialect does not correspond to
* any of the implemented lexer.
* * -INVALID_OPERATION when the lexer could not parse the keyword into
* a token or it returned a token which is not
* supported by the interpreter.
*/
int bfi_execute(char* program, size_t length, enum bfi_dialects dialect, char print_num);
/* Default, aka output of the interpreted program */
#define COLOR_RST CREATE_COLOR(NORMAL, DEFAULT_COLOR, DEFAULT_COLOR)
/* Messages from the interpreter. */
#define COLOR_MSG CREATE_COLOR(BOLD, DEFAULT_COLOR, DEFAULT_COLOR)
/* Error messages*/
#define COLOR_ERR CREATE_COLOR(BOLD, RED, DEFAULT_COLOR)
#endif /* _INTERPRETOR_H_ */

199
main.c Executable file
View File

@@ -0,0 +1,199 @@
/*
* Created by Lionel Sambuc on 03.12.09.
* Copyright 2009. All rights reserved.
*
*/
/**************************************************************************
* Brainfuck and derivative interpreter *
**************************************************************************/
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include "interpreter.h"
static struct
{
enum bfi_dialects dialect;
char print_num;
char dialect_override;
char const *filename;
FILE *file;
char *buffer;
size_t size;
}
options;
/**************************************************************************
* PRIVATE INTERFACE *
**************************************************************************/
/**
* Prints a short help.
*/
static void usage(void)
{
printf("Usage : bfi [-b|-e] [-h] [-n] filename\n"
"\t-b Force plain brainfuck.\n"
"\t-e Force Heu dialect.\n"
"\t-n Print memory cells as numbers instead of characters.\n");
}
/**
* Parses the parameters given on the command line.
*/
static int parse_cmd_line(int argc, const char *argv[])
{
int i;
char const *extension;
options.dialect = -1;
options.filename = NULL;
options.dialect_override = 0;
options.print_num = 0;
for(i = 1; i < argc; i++) {
/* The help option was activated. */
if(strncmp("-h", argv[i], 2) == 0)
{
usage();
return -2;
}
/* The brainfuck dialect override is activated */
if(strncmp("-b", argv[i], 2) == 0 && options.dialect_override != 1)
{
options.dialect = BRAINFUCK;
options.dialect_override = 1;
continue;
}
/* The Heu dialect override is activated */
if(strncmp("-e", argv[i], 2) == 0 && options.dialect_override != 1)
{
options.dialect = HEU;
options.dialect_override = 1;
continue;
}
/* Print memory cell values as number instead of characters. */
if(strncmp("-n", argv[i], 2) == 0)
{
options.print_num = 1;
continue;
}
for(extension = argv[i] + strlen(argv[i]);
*extension != '.' && extension >= argv[i];
extension--) /* Work already done! */;
if(extension != argv[i])
{
if(strncmp(extension, ".bf", 3) == 0 && options.dialect == -1)
options.dialect = BRAINFUCK;
if(strncmp(extension, ".heu", 3) == 0 && options.dialect == -1)
options.dialect = HEU;
}
options.filename = argv[i];
}
if(options.dialect == -1 || options.filename == NULL)
return -1;
return 0;
}
/**
* Open and load into memory the given program.
* Return 0 on succes or any error as set by fopen, malloc and fread.
*/
static int init(void)
{
int read = 0;
struct stat file_stats;
options.file = fopen(options.filename, "rb");
if(options.file == NULL)
return errno;
/* Retrieve the file size. */
fstat(fileno(options.file), &file_stats);
options.size = file_stats.st_size;
/* Allocate the memory buffer for the content of the file.
* We add one to ensure the buffer is terminated by at least one null
* character. */
options.buffer = malloc(options.size + 1);
if(options.buffer == NULL)
return errno;
/* Read the file into memory. */
read = fread(options.buffer, sizeof(char), options.size, options.file);
if(read != options.size)
return errno;
/* Append the null character. */
options.buffer[options.size] = '\0';
/* Close the file, as we don't need it anymore. */
fclose(options.file);
return 0;
}
/**************************************************************************
* PUBLIC INTERFACE *
**************************************************************************/
int main(int argc, const char *argv[])
{
int err;
/* Load parameters. */
if((err = parse_cmd_line(argc, argv)) != 0)
{
if(err != -2)
{
printf(COLOR_ERR "Error during argument parsing." COLOR_RST "\n");
usage();
return 1;
}
else
return 0;
}
/* Initialize the program buffer. */
if((err = init()) != 0)
{
perror("init");
printf(COLOR_ERR "Error during the loading of '%s'." COLOR_RST "\n", options.filename);
return 1;
}
/* Print the program as loaded into memory. */
printf(COLOR_MSG "Program : \n%s" COLOR_RST "\n", options.buffer);
/* Execute the program. */
printf(COLOR_MSG "Starting execution :" COLOR_RST "\n");
if((err = bfi_execute(options.buffer, options.size, options.dialect, options.print_num)) > 255)
{
/* Return the allocated memory, and print the interpretation error. */
free(options.buffer);
printf(COLOR_ERR "Error %i during execution" COLOR_RST "\n", err);
return err;
}
/* Return the allocated memory and print the program's ending code. */
free(options.buffer);
printf(COLOR_MSG "Execution ended with return value %i." COLOR_RST "\n", err);
/* Return succes to the shell. */
return 0;
}

56
tokenizer.c Executable file
View File

@@ -0,0 +1,56 @@
/*
* Created by Lionel Sambuc on 03.dec.2009.
* Copyright 2009. All rights reserved.
*
*/
/**************************************************************************
* Tokenizer functions *
**************************************************************************/
#include <stddef.h>
#include <string.h>
#include "tokenizer.h"
int (*tk_is_separator)(char c) = tk_is_white_space;
/**************************************************************************
* PRIVATE INTERFACE *
**************************************************************************/
/* Nothing ATM */
/**************************************************************************
* PUBLIC INTERFACE *
**************************************************************************/
int tk_is_white_space(char c)
{
return c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\v';
}
int tk_next_token(char const *str, int *from, size_t *length)
{
const int taille = strlen(str);
int i;
/* Skip all the separators starting from *from */
while ((*from < taille) && tk_is_separator(str[*from])) ++(*from);
/* Go ahead until the first separator is found or the end of the string. */
*length = 0;
for (i = *from; ((i < taille) && !tk_is_separator(str[i])); ++(*length), ++i);
return (*length != 0);
}
int tk_previous_token(char const *str, int *from, size_t *length)
{
int i;
/* Skip all the separators starting from *from */
while ((*from > 0) && tk_is_separator(str[*from])) --(*from);
/* Go back until the first separator is found or the start of the string. */
*length = 0;
for (i = *from; ((i > 0) && !tk_is_separator(str[i])); ++(*length), --i);
return (*length != 0);
}

47
tokenizer.h Executable file
View File

@@ -0,0 +1,47 @@
/*
* Created by Lionel Sambuc on 03.dec.2009.
* Copyright 2009. All rights reserved.
*
*/
/**************************************************************************
* Tokenizer interface *
**************************************************************************/
#ifndef _TOKENIZER_H_
#define _TOKENIZER_H_
/**
* This function pointer has to be initialized before any call to the
* tk_next_token or tk_previous_token. If not, the default separator
* (tk_is_white_space) will be used.
*
* As this vairable is globally shared, ensure it always points to the
* separator detector you wish before calling the tk_*_token function, as well
* as not modify it during their execution.
*/
extern int (*tk_is_separator)(char c);
/**
* This function return 1 if c is one of the following characters,
* otherwise 0 :
* ' ' : space
* '\t' : horizontal tabulation
* '\v' : vertical tabulation
* '\r' : carriage return
* '\n' : line feed
*/
int tk_is_white_space(char c);
/**
* Moves from to the first character of the next token and updates length to
* it's total length. Return 1 on success or 0 if the token wasn't found.
*/
int tk_next_token(char const *str, int *from, size_t *length);
/**
* Moves from to the last character of the previous token and updates length
* to it's total length. Return 1 on success or 0 if the token wasn't found.
*/
int tk_previous_token(char const *str, int *from, size_t *length);
#endif /* _TOKENIZER_H_ */