Parser
Example Usage
To demonstrate the usage of the libparser library, the below program parses the Ix programming language and converts it to simple Java.
Includes
The program uses the C standard library, the C standard IO library, the libtokenizer library, and the libparser library.
#include <stdlib.h>
#include <stdio.h>
#include "libparser/libparser.h"
#include "libtokenizer/PushbackReader.h"
Program Structure
Execution begins in the 'main' function and recursively descends into either the printPackage, printClass, printFunction, or printStatement function, depending on the AST (Abstract Syntax Tree) nodes traversed.
int main( int argc, char** argv );
//
void printPackage ( NodeIterator* it );
void printClass ( NodeIterator* it );
void printFunction( NodeIterator* it );
Functions
Function: main
int main( int argc, char** argv )
{
if ( 1 < argc )
{
const char* filepath = argv[1];
Parser* parser = Parser_NewFromFile ( filepath );
AST* ast = Parser_parse ( parser );
/*
const Node* root = AST_getRoot ( ast );
NodeIterator* it = Node_iterator ( root );
while ( NodeIterator_hasNext( it ) )
{
const Node child = NodeIterator_next( it );
{
switch ( child->nodeType )
{
case NODE_PACKAGE:
printPackage( it );
break;
case NODE_CLASS:
printClass( it );
break;
case NODE_FUNCTION:
printFunction( it );
break;
}
}
}
NodeIterator_free( &it );
Parser_free ( &parser );
*/
Parser_free( &parser );
}
return 0;
}
Main include
#ifndef LIBPARSER_STRUCTS_H
#define LIBPARSER_STRUCTS_H
typedef struct _AST AST;
typedef struct _Node Node;
typedef struct _NodeIterator NodeIterator;
typedef struct _Parser Parser;
#endif
#ifndef LIBPARSER_LIBPARSER_H
#define LIBPARSER_LIBPARSER_H
Includes
#include "libtokenizer/Base.h"
#include "libtokenizer/Runtime.h"
#include "libtokenizer/Tokenizer.h"
Types
#include "libparser/AST.h"
#include "libparser/Node.h"
#include "libparser/NodeIterator.h"
#include "libparser/Parser.h"
#endif
Parser
#ifndef LIBPARSER_PARSER_H
#define LIBPARSER_PARSER_H
#include "libparser/structs.h"
struct _Parser
{
Tokenizer* tokenizer;
AST* ast;
};
Parser* Parser_NewFromFile( const char* filepath );
Parser* Parser_new ( Tokenizer** tokenizer );
Parser* Parser_free ( Parser** self );
AST* Parser_parse( Parser* self );
#endif
Constructor
#include <stdlib.h>
#include "libparser/libparser.h"
Parser* Parser_NewFromFile( const char* filepath )
{
PushbackReader* reader = PushbackReader_new( filepath );
Tokenizer* tokenizer = Tokenizer_new( &reader );
Parser* parser = Parser_new( &tokenizer );
return parser;
}
Parser* Parser_new( Tokenizer** tokenizer )
{
Parser* self = Runtime_Calloc( 1, sizeof( Parser ) );
if ( self )
{
self->tokenizer = *tokenizer;
*tokenizer = NULL;
}
return self;
}
Destructor
Parser* Parser_free( Parser** self )
{
if ( (*self) && (*self)->tokenizer )
{
(*self)->tokenizer = Tokenizer_free( &(*self)->tokenizer );
}
return ((*self) = Runtime_Free( *self ));
}
AST* Parser_parse( Parser* self )
{
/*
if ( self->tokenizer )
{
Node* root = Node_new( Tokenizer_next( self->tokenizer ) );
if ( root )
{
self->ast = AST_new( root );
}
}
return self->ast;
*/
return NULL;
}
#include <stdlib.h>
#include "libparser/libparser.h"
const Node* AST_getRoot( AST* ast )
{
return NULL;
}
AST
#ifndef LIBPARSER_AST_H
#define LIBPARSER_AST_H
#include "libparser/structs.h"
struct _AST
{
Node* root;
};
AST* AST_new ( Node* root );
const Node* AST_getRoot( AST* ast );
#endif
Node
Class Definitions
#ifndef LIBPARSER_NODE_H
#define LIBPARSER_NODE_H
#include "libparser/structs.h"
struct _Node
{
const Node* parent;
Token* token;
Node** children;
};
Node* Node_new ( const Node* parent, Token** token );
NodeIterator* Node_iterator( const Node* self );
#endif
Constructor
Node* Node_new( const Node* parent, Token** token )
{
Node* self = Runtime_Calloc( 1, sizeof( Node ) );
if ( self )
{
self->parent = parent;
self->token = *token;
self->children = NULL; // Array
}
return self;
}
Destructor
Node* Node_free( Node** self )
{
Node* _self = *self;
if ( _self )
{
Token_free( _self->token );
// Array_free( _self->children );
}
return (*self = NULL);
}
Node_iterator
NodeIterator* Node_iterator( const Node* self )
{
return NULL;
}
Node
Class Definitions
#ifndef LIBPARSER_NODEITERATOR_H
#define LIBPARSER_NODEITERATOR_H
#include "libparser/structs.h"
struct _NodeIterator
{
const Node* parent;
Node* current;
};
NodeIterator* NodeIterator_new ( const Node* parent );
NodeIterator* NodeIterator_free ( NodeIterator** self );
bool NodeIterator_hasNext( NodeIterator* self );
Node* NodeIterator_next ( NodeIterator* self );
#endif
Constructor
NodeIterator* NodeIterator_new( const Node* parent )
{
NodeIterator* self = Runtime_Calloc( 1, sizeof( NodeIterator ) );
if ( self )
{
self->parent = parent;
self->current = NULL;
}
return self;
}
Destructor
NodeIterator* NodeIterator_free( NodeIterator** self )
{
NodeIterator* _self = *self;
if ( _self )
{
_self->parent = NULL;
_self->current = NULL;
}
return (*self = NULL);
}
bool NodeIterator_hasNext( NodeIterator* self )
{
return FALSE;
}
Node* NodeIterator_next( NodeIterator* self )
{
return NULL;
}
Make
CFLAGS=-O0
BIN=bin
DEP=dep/libtokenizer/obj/c/*.o
INC=-Iinclude -Idep/libtokenizer/include
LIB=lib
OBJ=obj
SRC=src
all: dirs c js tests
dirs:
mkdir -p $(BIN) $(OBJ) $(OBJ)/c $(LIB)
c: dirs
cc -c $(CFLAGS) $(INC) -o $(OBJ)/c/AST.o $(SRC)/c/AST.c
cc -c $(CFLAGS) $(INC) -o $(OBJ)/c/Node.o $(SRC)/c/Node.c
cc -c $(CFLAGS) $(INC) -o $(OBJ)/c/NodeIterator.o $(SRC)/c/NodeIterator.c
cc -c $(CFLAGS) $(INC) -o $(OBJ)/c/Parser.o $(SRC)/c/Parser.c
js:
mkdir -p $(LIB)/js
cat $(SRC)/js/*.js > $(LIB)/js/libparser.js
tests:
cc $(CFLAGS) $(INC) -o $(BIN)/testParser $(SRC)/c/testParser.c $(OBJ)/c/*.o $(DEP)
.PHONY: test
test:
$(BIN)/testParser > /dev/null
libtokenizer=libtokenizer/lib/libtokenizer.a
all: libtokenizer $(libtokenizer)
libtokenizer:
git clone https://github.com/CrossAdaptive/libtokenizer.git
$(libtokenizer):
make -C libtokenizer all tests test
clean:
rm -rf libtokenizer