Solved

C Program Formatter written in Java

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

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

Suggested Solutions

Title # Comments Views Activity
json example 39 132
eclipse java  build path 6 44
JavaScript/Java - Changing an image background color 4 56
object oriented programming comparison 5 55
Iteration: Iteration is repetition of a process. A student who goes to school repeats the process of going to school everyday until graduation. We go to grocery store at least once or twice a month to buy products. We repeat this process every mont…
Introduction This article explores the design of a cache system that can improve the performance of a web site or web application.  The assumption is that the web site has many more “read” operations than “write” operations (this is commonly the ca…
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:
Viewers will learn about if statements in Java and their use The if statement: The condition required to create an if statement: Variations of if statements: An example using if statements:

920 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

18 Experts available now in Live!

Get 1:1 Help Now