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