Solved

C Program Formatter written in Java

Posted on 2013-11-17
1
343 Views
Last Modified: 2013-11-18
I am working on a project to implement a Java program that adjusts the formatting of a C program.  A few weeks ago we implemented the lexical analyzer to do this and were given a formatter class to work with.  For this stage of the project we are now required to implement the if, for, while, and do loops in this formatter class.  I feel like I have the correct abstract idea of how to do this, however am having trouble translating this into the code required.  I am currently focusing on the IF statements, once I have completed the IF statements I will have a better understanding of completing the other statements.

The tokens that I have implemented are:
enum Token {NOT_FOUND, UPPER_CASE_IDENTIFIER, CONSTANT, COMMENT,
     COMPILER_DIRECTIVE, ASSIGNMENT_OPERATOR,
     PRE_OR_POST_UNARY_OPERATOR, STRUCTURE_OPERATOR,
     UNARY_OR_BINARY_OPERATOR,UNARY_OPERATOR, BINARY_OPERATOR,
     TERNARY_OPERATOR, COLON, LEFT_PARENTHESIS, RIGHT_PARENTHESIS,
     LEFT_BRACKET, RIGHT_BRACKET, LEFT_BRACE, RIGHT_BRACE, SEMICOLON,
     COMMA, STRING, SC_SPECIFIER, BREAK, CASE, TYPE_SPECIFIER,
     CONTINUE, DEFAULT, DO, ELSE, FOR, GOTO, IF, RETURN, SIZEOF,
     STATUS, STRUCT, SWITCH, UNION, WHILE, IDENTIFIER, FIRST, NONE,
     END_OF_FILE}

Open in new window


And the format class is as follows.  I have added nothing more than the function skeleton with comments inside trying to map out the ideas of what I am attempting to do.  As well as a few commented-out lines in the statement class.

class Format
{
    private Lexer lexer;
    private Output output;
    private Token token;

    //  The constructor establishes the input lexer and the output
    //    private data members.

    public Format(Lexer lexer, Output output)
    {
        this.lexer = lexer;
        this.output = output;
    }

    //  file is the only public method. External
    //    declarations are formatted until a function is found, at 
    //    which time functionBody is called to format it.

    public void file()
    {
        token = lexer.getNextToken();
        while (token != Token.END_OF_FILE)
            if (externalDeclaration())
                functionBody();
    }

    //  functionBody formats the declarations and statements in a
    //    function body.

    private void functionBody()
    {
        output.endLine(true);
        while (token == Token.TYPE_SPECIFIER ||
            token == Token.SC_SPECIFIER ||
            token == Token.STRUCT || token == Token.UNION ||
            token == Token.UPPER_CASE_IDENTIFIER)
            parameterDeclaration();
        output.indent();
        output.endLine(false);
        output.skipLine();
        compoundStatement();
        output.unindent();
        output.endLine(false);
        output.endPage();
    }


    // compoundStatement formats a multiple statement block

    private void compoundStatement()
    {
        int noOfDeclarations= 0;
        token = lexer.getNextToken();
        output.endLine(false);
        while (token == Token.TYPE_SPECIFIER ||
            token == Token.SC_SPECIFIER ||
            token == Token.STRUCT || token == Token.UNION ||
            token == Token.UPPER_CASE_IDENTIFIER)
        {
            declaration();
            noOfDeclarations++;
        }
        if (noOfDeclarations > 0)
            output.skipLine();
        while (token != Token.RIGHT_BRACE)
            statement();
        token = lexer.getNextToken();
        output.endLine(false);
    }

    //  statement determines the type of statement and calls the
    //    appropriate function to format it.

    private void statement()
    {
        if (token == Token.IDENTIFIER)
            if ((token = lexer.getNextToken()) == Token.COLON)
                token = lexer.getNextToken();
            else
            {
                token = Token.IDENTIFIER;
                lexer.putLastToken();
            }
        switch (token)
        {
            case LEFT_BRACE:
                compoundStatement();
                break;
            case SWITCH:
                switchStatement();
                break;
            case BREAK:
            case CONTINUE:
                verifyNextToken(Token.SEMICOLON);
                output.endLine(false);
               break;
            case RETURN:
                if ((token = lexer.getNextToken()) != Token.SEMICOLON)
                    {
                    expression(Token.SEMICOLON);
                    token = lexer.getNextToken();
                    }
                else
                    token = lexer.getNextToken();
                output.endLine(false);
                break;
            case GOTO:
                verifyNextToken(Token.IDENTIFIER);
                verifyNextToken(Token.SEMICOLON);
                output.endLine(false);
                break;
            // insert IF statement case
            /*case IF:
                ifStatement();
                break;*/
            default:
                expression(Token.SEMICOLON);
                token = lexer.getNextToken();
                output.endLine(false);
            }
        }

     //  switchStatement formats a switch statement.

    private void switchStatement()
    {
        verifyNextToken(Token.LEFT_PARENTHESIS);
        expression(Token.RIGHT_PARENTHESIS);
        token = lexer.getNextToken();
        output.endLine(false);
        output.indent();
        verifyCurrentToken(Token.LEFT_BRACE);
        output.endLine(false);
        while (token == Token.CASE || token == Token.DEFAULT)
        {
            if (token == Token.CASE)
            {
                expression(Token.COLON);
                lexer.adjustSpacing(Lexer.SUPPRESS_LEADING_SPACE);
                token = lexer.getNextToken();
                output.endLine(false);
                output.indent();
                while (token != Token.CASE && token !=
                    Token.DEFAULT && token != Token.RIGHT_BRACE)
                statement();
                output.unindent();
            }
            else
            {
                expression(Token.COLON);
                lexer.adjustSpacing(Lexer.SUPPRESS_LEADING_SPACE);
                token = lexer.getNextToken();
                output.endLine(false);
                output.indent();
                while (token != Token.CASE && token != Token.DEFAULT &&
                    token != Token.RIGHT_BRACE)
                    statement();
                output.unindent();
            }
        }
        verifyCurrentToken(Token.RIGHT_BRACE);
        output.endLine(false);
        output.unindent();
    }
    
    // if statement
    private void ifStatement()
    {
        // the next token should be a left parenthesis
        // followed by an expression
        // followed by a right parenthesis token
        // followed by a statement
        // possibly followed by an 'else' token
        // followed by a statement
    }
    
    // for statement
    private void forStatement()
    {
        // the next token should be a left parenthesis
        // followed by an expression
        // followed by a semicolon token
        // followed by an expression
        // followed by a semicolon token
        // followed by an expression
        // followed by a right parenthesis token
        // followed by a statement
    }
    
    // while statement
    private void whileStatement()
    {
        // next token is a left parenthesis
        // followed by an expression
        // followed by a right parenthesis token
        // followed by a statement
        
    }
    
    // do statement
    private void doStatement()
    {
        // next token is a statement
        // followed by a while token
        // followed by a left parenthesis token
        // followed by an expression
        // followed by a right parenthesis token
    }
    
    // externalDeclarations formats external declarations such as
    //   global variables and function prototypes. It returns if
    //   it encounters a function heading.

    private boolean externalDeclaration()

    {
        int braceCount = 0;
        boolean indentAtSemicolon = false;
        Token lastToken = Token.NOT_FOUND;
        while ((braceCount > 0) || (token != Token.SEMICOLON))
        {
            lexer.checkDeclarationSpacing(token);
            if (token == Token.LEFT_BRACE)
            {
                output.endLine(false);
                output.indent();
                lastToken = token;
                token = lexer.getNextToken();
                output.endLine(false);
                braceCount++;
            }
            else if (token == Token.RIGHT_BRACE)
            {
                lastToken = token;
                token = lexer.getNextToken();
                indentAtSemicolon = true;
                braceCount--;
            }
            else if (token == Token.LEFT_PARENTHESIS)
            {
                lastToken = token;
                token = lexer.getNextToken();
            }
            else if (token == Token.RIGHT_PARENTHESIS)
            {
                lastToken = token;
                token = lexer.getNextToken();
                if (token != Token.SEMICOLON)
                    return true;
            }
            else if (token == Token.ASSIGNMENT_OPERATOR)
                while (token != Token.SEMICOLON)
                {
                    lastToken = token;
                    token = lexer.getNextToken();
                    lexer.checkExpressionSpacing(token, lastToken);
                }
            else if (token == Token.SEMICOLON)
            {
                lastToken = token;
                token = lexer.getNextToken();
                if (braceCount > 0)
                    output.endLine(false);
                if (indentAtSemicolon)
                {
                    output.indent();
                    indentAtSemicolon = false;
                }
            }
            else
            {
                lastToken = token;
                token = lexer.getNextToken();
            }
        }

        token = lexer.getNextToken();
        output.endLine(false);
        if (indentAtSemicolon)
            output.indent();
        return false;
    }

    //  parameterDeclaration formats parameter declarations.

    private void parameterDeclaration()

    {
        int braceCount = 0;
        while ((braceCount > 0) || (token != Token.SEMICOLON))
        {
            lexer.checkDeclarationSpacing(token);
            if (token == Token.LEFT_BRACE)
            {
                output.endLine(false);
                output.indent();
                token = lexer.getNextToken();
                output.endLine(false);
                braceCount++;
            }
        else if (token == Token.RIGHT_BRACE)
            {
                token = lexer.getNextToken();
                output.indent();
                braceCount--;
            }
        else if ((braceCount > 0 ) && (token == Token.SEMICOLON))
            {
                token = lexer.getNextToken();
                output.endLine(false);
            }
        else
            token = lexer.getNextToken();
        }
        token = lexer.getNextToken();
        output.endLine(false);
    }

    // declaration formats local declarations.

    private void declaration()

    {
        int braceCount = 0;
        boolean indentAtSemicolon = false;

        while ((braceCount > 0) || (token != Token.SEMICOLON))
        {
            lexer.checkDeclarationSpacing(token);
            if (token == Token.LEFT_BRACE)
            {
                output.endLine(false);
                output.indent();
                token = lexer.getNextToken();
                output.endLine(false);
                braceCount++;
            }
            else if (token == Token.RIGHT_BRACE)
            {
                token = lexer.getNextToken();
                indentAtSemicolon = true;
                braceCount--;
            }
            else if (token == Token.SEMICOLON)
            {
                token = lexer.getNextToken();
                if (braceCount > 0)
                    output.endLine(false);
                if (indentAtSemicolon)
                {
                    output.indent();
                    indentAtSemicolon = false;
                }
            }
            else if (token == Token.ASSIGNMENT_OPERATOR)
                expression(Token.SEMICOLON);
            else
                token = lexer.getNextToken();
        }
        token = lexer.getNextToken();
        output.endLine(false);
        if (indentAtSemicolon)
            output.indent();
    }

    //  expression formats an expression. The delimiting token must
    //    be provided.

    private void expression(Token terminator)
    {
        Token lastToken;

        lastToken = Token.NOT_FOUND;
        while (token != terminator)
        {
            lexer.checkExpressionSpacing(token, lastToken);

            if (token == Token.LEFT_PARENTHESIS)
            {
                if (lastToken == Token.IDENTIFIER ||
                    lastToken == Token.UPPER_CASE_IDENTIFIER)
                    lexer.adjustSpacing(Lexer.SUPPRESS_LEADING_SPACE);
                token = lexer.getNextToken();
                expression(Token.RIGHT_PARENTHESIS);
            }
            lastToken = token;
            token = lexer.getNextToken();
        }
    }

    // Gets the next token and then verifies that the supplied token is
    //   the required token.

    private void verifyNextToken(Token requiredToken)
    {
        token = lexer.getNextToken();
        verifyCurrentToken(requiredToken);
    }

    // Verifies that the supplied token is the current token.
    // Displays an error message if it is not.

    private void verifyCurrentToken(Token requiredToken)
    {
        if (token != requiredToken)
            output.outputError("MISSING " + requiredToken.name());
        else
            token = lexer.getNextToken();

    }
}

Open in new window


I am looking for help implementing the IF statement formatter.  Do I have the correct “steps” to allow the program to recognize an if statement?  I think I can get an idea of how to complete the first few steps by following the example of the switch statement class, however I am unsure after recognizing the initial logical expression where to begin making it read through the rest of the if statement.  Any help at all would be appreciated.
0
Comment
Question by:Autkast
1 Comment
 
LVL 27

Accepted Solution

by:
dpearson earned 400 total points
ID: 39655593
Yes this structure looks correct:

    // if statement
    private void ifStatement()
    {
        // the next token should be a left parenthesis
        // followed by an expression
        // followed by a right parenthesis token
        // followed by a statement
        // possibly followed by an 'else' token
        // followed by a statement
    }

Open in new window


And the code itself will start off something like this I believe:

 
   private void ifStatement()
    {
       verifyNextToken(Token.LEFT_PARENTHESIS);
       expression(Token.RIGHT_PARENTHESIS);
       statement() ;
       ...
    }

Open in new window


I hope that helps get you started,

Doug
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
custom annotations 9 42
javap bin 2 40
Java program running SQL query 5 37
DirectoryWatch - Any Algorithm to get workable result with ReadDirectoryChangesW() 3 39
Software development teams often use in-memory caches to improve performance. They want to speed up access to, or reduce load on, a backing store (database, file system, etc.) by keeping some or all of the data in memory.   You should implement a …
Introduction This question got me thinking... (http://www.experts-exchange.com/questions/28707487/GLOBALS.html) Why shouldn't we use Globals? This is a simple question without a simple answer.  How do you explain these concepts to a programmer w…
Viewers will learn one way to get user input in Java. Introduce the Scanner object: Declare the variable that stores the user input: An example prompting the user for input: Methods you need to invoke in order to properly get  user input:
This tutorial covers a step-by-step guide to install VisualVM launcher in eclipse.

856 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question