Solved

C Program Formatter written in Java

Posted on 2013-11-17
1
328 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 26

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

What Should I Do With This Threat Intelligence?

Are you wondering if you actually need threat intelligence? The answer is yes. We explain the basics for creating useful threat intelligence.

Join & Write a Comment

Introduction Many of the most common information processing tasks require sorting data sets.  For example, you may want to find the largest or smallest value in a collection.  Or you may want to order the data set in numeric or alphabetical order. …
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
Viewers learn how to read error messages and identify possible mistakes that could cause hours of frustration. Coding is as much about debugging your code as it is about writing it. Define Error Message: Line Numbers: Type of Error: Break Down…
This tutorial covers a practical example of lazy loading technique and early loading technique in a Singleton Design Pattern.

708 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

Need Help in Real-Time?

Connect with top rated Experts

12 Experts available now in Live!

Get 1:1 Help Now