Last active
December 15, 2015 13:38
-
-
Save nsmaciej/5268222 to your computer and use it in GitHub Desktop.
Sample parser - by James Crook
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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