Solved

C Program Formatter written in Java

Posted on 2013-11-17
1
358 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
1 Comment
 
LVL 28

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

Get 15 Days FREE Full-Featured Trial

Benefit from a mission critical IT monitoring with Monitis Premium or get it FREE for your entry level monitoring needs.
-Over 200,000 users
-More than 300,000 websites monitored
-Used in 197 countries
-Recommended by 98% of users

Question has a verified solution.

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

Introduction A frequently used term in Object-Oriented design is "SOLID" which is a mnemonic acronym that covers five principles of OO design.  These principles do not stand alone; there is interplay among them.  And they are not laws, merely princ…
When there is a disconnect between the intentions of their creator and the recipient, when algorithms go awry, they can have disastrous consequences.
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …
Suggested Courses

615 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