Skip to content

Instantly share code, notes, and snippets.

@nsmaciej
Last active December 15, 2015 13:38
Show Gist options
  • Save nsmaciej/5268222 to your computer and use it in GitHub Desktop.
Save nsmaciej/5268222 to your computer and use it in GitHub Desktop.
Sample parser - by James Crook
#include <stdio.h>
char * pSource;
int bDone;
int bOpMatched;
int iNestDepth;
int iNumber;
extern int atoi();
typedef int bool;
#define true (1)
#define false (0)
void Init(char * pToParse);
bool IsWhiteSpace(char ch);
void SkipWhiteSpace();
void SkipTokenAndSpace( int iTokenLength );
void MarkBadToEnd( char * pMsg );
void Atom( );
void Number();
void MustCloseBrace();
void Expr( );
void MultExpr( );
bool ExprExt( );
bool MultExprExt( );
void Evaluate( char *pSource );
void Init(char * pToParse)
{
pSource = pToParse;
bDone = 0;
bOpMatched = 1;
iNestDepth = 0;
iNumber = 0;
}
bool IsWhiteSpace(char ch)
{
if( ch==' ' )
return true;
return false;
}
void SkipWhiteSpace()
{
while( pSource[0] != '\0' )
{
if( !IsWhiteSpace(pSource[0]))
return;
}
}
void SkipTokenAndSpace( int iTokenLength )
{
pSource += iTokenLength;
SkipWhiteSpace();
}
void MarkBadToEnd( char * pMsg )
{
bDone = true;
printf( "%s", pMsg );
return;
}
void Atom( )
{
char FirstChar;
char * pNumberStart;
if( bDone || !bOpMatched )
return;
FirstChar = pSource[0];
switch( FirstChar )
{
case '(':
{
iNestDepth++;
SkipTokenAndSpace(1);
Expr( );
MustCloseBrace();
}
break;
case '-':
{
SkipTokenAndSpace(1);
Expr( );
iNumber = -iNumber;
}
break;
default:
break;
}
pNumberStart = pSource;
while( ('0' <= pSource[0]) && (pSource[0] <= '9'))
pSource++;
if( pNumberStart == pSource )
{
// MarkBadToEnd( "Expecting a number" );
}
else
{
iNumber = atoi( pNumberStart );
SkipWhiteSpace();
}
}
void Number()
{
if( bDone || !bOpMatched )
return;
iNestDepth=0;
Expr( );
if( iNestDepth > 0 )
{
MarkBadToEnd( "Missing closing braces");
}
}
void MustCloseBrace()
{
char Char = '#';
if( iNestDepth <= 0 )
{
MarkBadToEnd( "Close closed brace");
return;
}
Char = pSource[0];
if( Char == ')')
{
iNestDepth--;
SkipTokenAndSpace(1);
}
else
{
MarkBadToEnd( "Required closing brace");
return;
}
}
void Expr()
{
if( bDone || !bOpMatched )
return;
MultExpr( );
while( ExprExt( ));
}
void MultExpr()
{
if( bDone || !bOpMatched )
return;
Atom( );
while( MultExprExt( ));
}
bool ExprExt( )
{
char FirstChar;
int iTempNumber;
if( bDone || !bOpMatched )
return false;
FirstChar = pSource[0];
iTempNumber = iNumber;
switch( FirstChar )
{
case '+':
SkipTokenAndSpace(1);
MultExpr( );
iNumber = iTempNumber + iNumber;
return true;
break;
case '-':
SkipTokenAndSpace(1);
MultExpr( );
iNumber = iTempNumber - iNumber;
return true;
break;
default:
break;
}
SkipWhiteSpace();
return false;
}
bool MultExprExt( )
{
char FirstChar = '#';
int iTempNumber = iNumber;
if( bDone || !bOpMatched )
return false;
FirstChar = pSource[0];
switch( FirstChar )
{
case '*':
SkipTokenAndSpace(1);
Atom( );
iNumber = iTempNumber * iNumber;
return true;
break;
case '/':
SkipTokenAndSpace(1);
Atom( );
if( iNumber == 0 )
MarkBadToEnd( "Division by zero");
else
iNumber = iTempNumber / iNumber;
return true;
break;
default:
break;
}
SkipWhiteSpace();
return false;
}
void Evaluate( char *pSource )
{
Init( pSource );
Expr();
printf(" Evaluate %s result is %i\n", pSource, iNumber );
}
int main( char * argc, char * argv)
{
char ch;
printf("Test Cases\n");
Evaluate( "3+4" );
Evaluate( "3+4*5" );
Evaluate( "3*4+5" );
Evaluate( "1+1+1+1+1" );
Evaluate( "2*(3*(4+(1+1)))" );
Evaluate( "(2*3)*(4+1)+1" );
ch = getchar();
}
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdbool.h>
char * line;
int errorFound,
bNest,
total;
void Atom( );
void MustCloseBrace();
void Expr( );
void MultExpr( );
bool ExprExt( );
bool MultExprExt( );
void eval( char *line );
void SkipWhiteSpace(){
for(; *line != '\0' ;++line)
if( *line != ' ')
break;
}
void skipOpAndSpace(long opLen){
line += opLen;
SkipWhiteSpace();
}
void showError(char *msg){
errorFound = true;
printf("%s", msg);
}
void Atom( ){
if( errorFound )
return;
switch(*line){
case '(':
bNest++;
skipOpAndSpace(1);
Expr();
MustCloseBrace();
break;
case '-':
skipOpAndSpace(1);
Expr();
total = -total;
break;
}
char *numStartAt = line;
while(isdigit(*line))
++line;
if( numStartAt == line ){
//showError("Expecting a number");
}else{
total = atoi(numStartAt);
printf("%d\n", total);
SkipWhiteSpace();
}
}
void MustCloseBrace(){
if(bNest <= 0){
showError( "Close closed brace");
return;
}
if(*line == ')'){
bNest--;
skipOpAndSpace(1);
}else{
showError("Required closing brace");
}
}
void Expr(){
if(errorFound)
return;
MultExpr( );
while( ExprExt( ));
}
void MultExpr(){
Atom();
while(!errorFound && MultExprExt( ));
}
bool ExprExt( ){
int tmpTotal = total;
switch(*line){
case '+':
skipOpAndSpace(1);
if(!errorFound)
MultExpr();
printf("+\n");
total = tmpTotal + total;
return true;
case '-':
skipOpAndSpace(1);
if(!errorFound)
MultExpr();
printf("-\n");
total = tmpTotal - total;
return true;
}
SkipWhiteSpace();
return false;
}
bool MultExprExt( ){
int tmpTotal = total;
switch(*line){
case '*':
skipOpAndSpace(1);
Atom( );
printf("*\n");
total = tmpTotal * total;
return true;
break;
case '/':
skipOpAndSpace(1);
Atom( );
printf("*\n");
if( total == 0 )
showError( "Division by zero");
else
total = tmpTotal / total;
return true;
break;
}
SkipWhiteSpace();
return false;
}
void eval(char *l){
line = l;
errorFound = false;
bNest = 0;
total = 0;
SkipWhiteSpace();
Expr();
printf("'%s' = %d\n", l, total );
}
int main(void){
eval("3+4*5");
eval("3*4+5");
eval("1+1+1+1+1");
eval("2*(3*(4+(1+1)))");
eval("(2*3)*(4+1)+1");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment