Skip to content

Commit

Permalink
Add BisonExample.
Browse files Browse the repository at this point in the history
  • Loading branch information
StackedCrooked committed May 18, 2018
1 parent 94e7925 commit 8efabc0
Show file tree
Hide file tree
Showing 6 changed files with 320 additions and 0 deletions.
66 changes: 66 additions & 0 deletions Playground/BisonExample/Expression.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* Expression.c
* Implementation of functions used to build the syntax tree.
*/

#include "Expression.h"

#include <stdlib.h>

/**
* @brief Allocates space for expression
* @return The expression or NULL if not enough memory
*/
static SExpression *allocateExpression()
{
SExpression *b = (SExpression *)malloc(sizeof(SExpression));

if (b == NULL)
return NULL;

b->type = eVALUE;
b->value = 0;

b->left = NULL;
b->right = NULL;

return b;
}

SExpression *createNumber(int value)
{
SExpression *b = allocateExpression();

if (b == NULL)
return NULL;

b->type = eVALUE;
b->value = value;

return b;
}

SExpression *createOperation(EOperationType type, SExpression *left, SExpression *right)
{
SExpression *b = allocateExpression();

if (b == NULL)
return NULL;

b->type = type;
b->left = left;
b->right = right;

return b;
}

void deleteExpression(SExpression *b)
{
if (b == NULL)
return;

deleteExpression(b->left);
deleteExpression(b->right);

free(b);
}
52 changes: 52 additions & 0 deletions Playground/BisonExample/Expression.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Expression.h
* Definition of the structure used to build the syntax tree.
*/
#ifndef __EXPRESSION_H__
#define __EXPRESSION_H__

/**
* @brief The operation type
*/
typedef enum tagEOperationType
{
eVALUE,
eMULTIPLY,
ePLUS
} EOperationType;

/**
* @brief The expression structure
*/
typedef struct tagSExpression
{
EOperationType type;///< type of operation

int value;///< valid only when type is eVALUE
struct tagSExpression *left; ///< left side of the tree
struct tagSExpression *right;///< right side of the tree
} SExpression;

/**
* @brief It creates an identifier
* @param value The number value
* @return The expression or NULL in case of no memory
*/
SExpression *createNumber(int value);

/**
* @brief It creates an operation
* @param type The operation type
* @param left The left operand
* @param right The right operand
* @return The expression or NULL in case of no memory
*/
SExpression *createOperation(EOperationType type, SExpression *left, SExpression *right);

/**
* @brief Deletes a expression
* @param b The expression
*/
void deleteExpression(SExpression *b);

#endif // __EXPRESSION_H__
44 changes: 44 additions & 0 deletions Playground/BisonExample/Lexer.l
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
%{

/*
* Lexer.l file
* To generate the lexical analyzer run: "flex Lexer.l"
*/

#include "Expression.h"
#include "Parser.h"

#include <stdio.h>

%}

%option outfile="Lexer.c" header-file="Lexer.h"
%option warn nodefault

%option reentrant noyywrap never-interactive nounistd
%option bison-bridge

LPAREN "("
RPAREN ")"
PLUS "+"
MULTIPLY "*"

NUMBER [0-9]+
WS [ \r\n\t]*

%%

{WS} { /* Skip blanks. */ }
{NUMBER} { sscanf(yytext, "%d", &yylval->value); return TOKEN_NUMBER; }

{MULTIPLY} { return TOKEN_MULTIPLY; }
{PLUS} { return TOKEN_PLUS; }
{LPAREN} { return TOKEN_LPAREN; }
{RPAREN} { return TOKEN_RPAREN; }
. { }

%%

int yyerror(const char *msg) {
fprintf(stderr,"Error:%s\n",msg); return 0;
}
17 changes: 17 additions & 0 deletions Playground/BisonExample/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Makefile

FILES = Lexer.c Parser.c Expression.c main.c
CC = g++
CFLAGS = -g -ansi

test: $(FILES)
$(CC) $(CFLAGS) $(FILES) -o test

Lexer.c: Lexer.l
flex Lexer.l

Parser.c: Parser.y Lexer.c
bison Parser.y

clean:
rm -f *.o *~ Lexer.c Lexer.h Parser.c Parser.h test
68 changes: 68 additions & 0 deletions Playground/BisonExample/Parser.y
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
%{

/*
* Parser.y file
* To generate the parser run: "bison Parser.y"
*/

#include "Expression.h"
#include "Parser.h"
#include "Lexer.h"
#include <iostream>

int yyerror(SExpression **expression, yyscan_t scanner, const char *msg)
{
// Add error handling routine as needed
std::cerr << msg << std::endl;
return 0;
}

%}

%code requires {

#ifndef YY_TYPEDEF_YY_SCANNER_T
#define YY_TYPEDEF_YY_SCANNER_T
typedef void* yyscan_t;
#endif

}

%output "Parser.c"
%defines "Parser.h"

%define api.pure
%lex-param { yyscan_t scanner }
%parse-param { SExpression **expression }
%parse-param { yyscan_t scanner }

%union {
int value;
SExpression *expression;
}

%left '+' TOKEN_PLUS
%left '*' TOKEN_MULTIPLY

%token TOKEN_LPAREN
%token TOKEN_RPAREN
%token TOKEN_PLUS
%token TOKEN_MULTIPLY
%token <value> TOKEN_NUMBER

%type <expression> expr

%%

input
: expr { *expression = $1; }
;

expr
: expr[L] TOKEN_PLUS expr[R] { $$ = createOperation( ePLUS, $L, $R ); }
| expr[L] TOKEN_MULTIPLY expr[R] { $$ = createOperation( eMULTIPLY, $L, $R ); }
| TOKEN_LPAREN expr[E] TOKEN_RPAREN { $$ = $E; }
| TOKEN_NUMBER { $$ = createNumber($1); }
;

%%
73 changes: 73 additions & 0 deletions Playground/BisonExample/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
* main.c file
*/

#include "Expression.h"
#include "Parser.h"
#include "Lexer.h"

#include <stdio.h>

int yyparse(SExpression **expression, yyscan_t scanner);

SExpression *getAST(const char *expr)
{
SExpression *expression;
yyscan_t scanner;
YY_BUFFER_STATE state;

if (yylex_init(&scanner)) {
// could not initialize
return NULL;
}

state = yy_scan_string(expr, scanner);

if (yyparse(&expression, scanner)) {
// error parsing
return NULL;
}

yy_delete_buffer(state, scanner);

yylex_destroy(scanner);

return expression;
}

int evaluate(SExpression *e)
{
switch (e->type) {
case eVALUE:
return e->value;
case eMULTIPLY:
return evaluate(e->left) * evaluate(e->right);
case ePLUS:
return evaluate(e->left) + evaluate(e->right);
default:
// should not be here
return 0;
}
}

void test(const char* text)
{
SExpression *e = NULL;

e = getAST(text);

int result = evaluate(e);

printf("Result of '%s' is %d\n", text, result);

deleteExpression(e);

}

int main(void)
{
test("4 ~ 3");
test("4 + 3");
test("4 + 2");
return 0;
}

0 comments on commit 8efabc0

Please sign in to comment.