Java 1.5 Parser - Grammar Rules - part 7

<- back

Next Chapter Grammar Rules - part 8

Expressions

Expressions will be implemented using the real Java Specification (Java Specification 5.0: Expression). Why? The Syntax Specification contains some minor errors (or typos) and the expressions need to be more specific to be able to build a AST.

ConditionalExpression

Lets begin with ConditionalExpression and a few more expression rules.

Java Syntax Rule
ConditionalExpression:
ConditionalOrExpression
ConditionalOrExpression ? Expression : ConditionalExpression

ConditionalOrExpression:
ConditionalAndExpression
ConditionalOrExpression || ConditionalAndExpression

ConditionalAndExpression:
InclusiveOrExpression
ConditionalAndExpression && InclusiveOrExpression

InclusiveOrExpression:
ExclusiveOrExpression
InclusiveOrExpression | ExclusiveOrExpression

ExclusiveOrExpression:
AndExpression
ExclusiveOrExpression ^ AndExpression

AndExpression:
EqualityExpression
AndExpression & EqualityExpression

EqualityExpression:
RelationalExpression
EqualityExpression == RelationalExpression
EqualityExpression != RelationalExpression

RelationalExpression:
ShiftExpression
RelationalExpression < ShiftExpression
RelationalExpression > ShiftExpression
RelationalExpression <= ShiftExpression
RelationalExpression >= ShiftExpression
RelationalExpression instanceof ReferenceType

ShiftExpression:
AdditiveExpression
ShiftExpression << AdditiveExpression
ShiftExpression >> AdditiveExpression
ShiftExpression >>> AdditiveExpression

AdditiveExpression:
MultiplicativeExpression
AdditiveExpression + MultiplicativeExpression
AdditiveExpression - MultiplicativeExpression

MultiplicativeExpression:
UnaryExpression
MultiplicativeExpression * UnaryExpression
MultiplicativeExpression / UnaryExpression
MultiplicativeExpression % UnaryExpression

UnaryExpression:
++ UnaryExpression
UnaryExpression
+ UnaryExpression
- UnaryExpression
UnaryExpressionNotPlusMinus

UnaryExpressionNotPlusMinus:
PostfixExpression
~ UnaryExpression
! UnaryExpression
CastExpression

PostfixExpression:
Primary
ExpressionName
PostfixExpression ++
PostfixExpression —

CastExpression:
( PrimitiveType ) UnaryExpression
( ReferenceType ) UnaryExpressionNotPlusMinus

The above rules must first be rewritten to get rid of the left recursion. ExpressionName is the same rule as QualifiedIdentifier.

Coco/R EBFN Rule
PRODUCTIONS

ConditionalExpression<out ConditionalExpression expr> =
ConditionalOrExpression [QuestonMark Expression< out expr> Colon
ConditionalExpression< out expr>].

ConditionalOrExpression =
ConditionalAndExpression {LogicOr ConditionalAndExpression}.

ConditionalAndExpression =
InclusiveOrExpression {LogicAnd InclusiveOrExpression}.

InclusiveOrExpression =
ExclusiveOrExpression {BitwiseOr ExclusiveOrExpression}.

ExclusiveOrExpression =
AndExpression {BitwiseXor AndExpression}.

AndExpression =
EqualityExpression {BitwiseAnd EqualityExpression}.

EqualityExpression =
RelationalExpression {Equal RelationalExpression} |
RelationalExpression {NotEqual RelationalExpression}.

RelationalExpression =
ShiftExpression {LesserThan ShiftExpression} |
ShiftExpression {GreaterThan ShiftExpression} |
ShiftExpression {LessanThanOrEqual ShiftExpression} |
ShiftExpression {GreaterThanOrEqual ShiftExpression} |
ShiftExpression {Instanceof ReferenceType}.

ShiftExpression =
AdditiveExpression {BitwiseShiftLeft AdditiveExpression} |
AdditiveExpression {BitwiseShiftRight AdditiveExpression} |
AdditiveExpression {BitwiseUnsignedShiftRight AdditiveExpression}.

AdditiveExpression =
MultiplicativeExpression {Plus MultiplicativeExpression} |
MultiplicativeExpression {Minus MultiplicativeExpression}.

MultiplicativeExpression =
UnaryExpression {Asterix UnaryExpression} |
UnaryExpression {Slash UnaryExpression} |
UnaryExpression {Modulo UnaryExpression}.

UnaryExpression =
{Increment | Decrement | Plus | Minus} UnaryExpressionNotPlusMinus.

UnaryExpressionNotPlusMinus =
PostfixExpression |
Tilde UnaryExpression |
ExclamationMark UnaryExpression |
CastExpression.

PostfixExpression =
(Primary | QualifiedIdentifier<out sbId>) {Increment | Decrement}.

CastExpression =
LeftParenthesis PrimitiveType RightParenthesis UnaryExpression |
LeftParenthesis ReferenceType RightParenthesis UnaryExpressionNotPlusMinus.

Compiling these rules above gives a lot of warnings. Lets rewrite them more compact

Coco/R EBFN Rule
PRODUCTIONS

ConditionalExpression<out ConditionalExpression expr> =
ConditionalOrExpression [QuestonMark Expression<out expr> Colon
ConditionalExpression<out expr>].

ConditionalOrExpression =
ConditionalAndExpression {LogicOr ConditionalAndExpression}.

ConditionalAndExpression =
InclusiveOrExpression {LogicAnd InclusiveOrExpression}.

InclusiveOrExpression =
ExclusiveOrExpression {BitwiseOr ExclusiveOrExpression}.

ExclusiveOrExpression =
AndExpression {BitwiseXor AndExpression}.

AndExpression =
EqualityExpression {BitwiseAnd EqualityExpression}.

EqualityExpression =
RelationalExpression {(Equal | NotEqual) RelationalExpression}.

RelationalExpression =
ShiftExpression {((LesserThan | GreaterThan | LessanThanOrEqual |
GreaterThanOrEqual) ShiftExpression) | (Instanceof ReferenceType)}.

ShiftExpression =
AdditiveExpression {(BitwiseShiftLeft | BitwiseShiftRight |
BitwiseUnsignedShiftRight) AdditiveExpression}.

AdditiveExpression =
MultiplicativeExpression {(Plus | Minus) MultiplicativeExpression}.

MultiplicativeExpression =
UnaryExpression {(Asterix | Slash | Modulo) UnaryExpression}.

UnaryExpression =
{Increment | Decrement | Plus | Minus} UnaryExpressionNotPlusMinus.

UnaryExpressionNotPlusMinus =
PostfixExpression |
Tilde UnaryExpression |
ExclamationMark UnaryExpression |
CastExpression.

PostfixExpression =
(Primary | QualifiedIdentifier<out sbId>) {Increment | Decrement}.

CastExpression =
LeftParenthesis ((PrimitiveType RightParenthesis UnaryExpression) |
(ReferenceType RightParenthesis UnaryExpressionNotPlusMinus)).

Before compiling a few dummy rules must be defined

Coco/R EBFN Rule
PRODUCTIONS

Expression<out ConditionalExpression expr> =
ConditionalExpression< out expr>.

ReferenceType =
QualifiedIdentifier<out sbId>.

Primary =
IntigerLiteral.

PrimitiveType =
Byte | Short | Int | Long | Char | Float | Double | Boolean.

Compiling these rules will display

checking
  Java15 deletable
  LL1 warning in ElementValuePair: Identifier is start & successor of deletable structure
parser generated
0 errors detected

Take a closer look at the rule ElementValuePair (not displaying associated actions)

Coco/R EBFN Rule
PRODUCTIONS

ElementValuePair<out ElementValuePair elementValuePair> =
[Identifier Assignment] ElementValue<out elementValue>.

An ElementValue is also a ConditionalExpression which boils down to a PostfixExpression which contains a starting QualifiedIdentifier. And a QualifiedIdentifier begins with an Identifier. So, an IF-clause in front of the optional Identifier in the ElementValuePair rule, which checks if a Identifier is followed by an Assignment would settle the conflict.

Coco/R EBFN Rule
PRODUCTIONS

ElementValuePair<out ElementValuePair elementValuePair> =
[IF(isIdentifierFollowedByAssignment()) Identifier Assignment]
ElementValue<out elementValue>.

Compiling now displays now warnings.

Abstract Syntax Tree Elements

UML class diagram

Quite a few AST elements are needed to be able to represent these expression rules.

iexpression_a.png

IExpression

IExpression is an interface that all expression elements inherit from.

package org.structuredparsing.java15grammar.ast;
 
public interface IExpression { }

TwoOperatorExpression

This class represents the expression A ? B : C and is the only two operator expression in Java.

package org.structuredparsing.java15grammar.ast;
 
public class TwoOperatorExpression implements IExpression {
    private IExpression leftExpression;
    private IExpression middleExpression;
    private IExpression rightRxpression;
 
    public void setLeftExpression( IExpression expression ) {
        this.leftExpression = expression;
    }
 
    public IExpression getLeftExpression() {
        return leftExpression;
    }
 
    public void setMiddleExpression( IExpression expression ) {
        this.middleExpression = expression;
    }
 
    public IExpression getMiddleExpression() {
        return middleExpression;
    }
 
    public void setRightExpression( IExpression expression ) {
        this.rightRxpression = expression;
    }
 
    public IExpression getRightExpression() {
        return rightRxpression;
    }
}

OperatorExpression

This class represents expressions on the form A Op B, where op is one of the "ordinary" operators like +, -, *, ==, <, instanceof, && and so on. The various operators are represented as an enum.

package org.structuredparsing.java15grammar.ast;
 
public enum OPERATOR {
    INCREMENT, DECREMENT, LOGIC_NOT, BITWISE_COMPLIMENT, PLUS, MINUS,
    LOGIC_OR, LOGIC_AND, BITWISE_OR, BITWISE_XOR, BITWISE_AND,
    EQUAL, NOT_EQUAL, LESSER_THAN, GREATER_THAN, 
    LESSER_THAN_OR_EQUAL, GREATER_THAN_OR_EQUAL,
    BITWISE_SHIFT_LEFT, BITWISE_SHIFT_RIGHT,
    BITWISE_UNSIGNED_SHIFT_RIGHT,
    MULTIPLICATION, MODULO, DIVIDE,
    INSTANCE_OF
}

The OperatorExpression

package org.structuredparsing.java15grammar.ast;
 
public class OperatorExpression implements IExpression {
    private IExpression leftExpression;
    private OPERATOR eOperator;
    private IExpression rightExpression;
 
    public void setLeftExpression( IExpression leftExpression ) {
        this.leftExpression = leftExpression;
    }
 
    public IExpression getLeftExpression() {
        return this.leftExpression;
    }
 
    public void setOperator( OPERATOR eOperator ) {
        this.eOperator = eOperator;
    }
 
    public OPERATOR getOperator() {
        return this.eOperator;
    }
 
    public void setRightExpression( IExpression rightExpression ) {
        this.rightExpression = rightExpression;
    }
 
    public IExpression getRightExpression() {
        return this.rightExpression;
    }
}

PrefixUnaryOperatorExpression

This represent prefix unary operator expression. Note that a list of operators may precede an expression.

package org.structuredparsing.java15grammar.ast;
 
import java.util.ArrayList;
import java.util.List;
 
public class PrefixUnaryOperatorExpression implements IExpression {
    private List<OPERATOR> unaryOperators;
    private IExpression expression;
 
    public UnaryExpression() {
        unaryOperators = new ArrayList< OPERATOR >();
    }
 
    public void addOperator( OPERATOR eOperator ) {
        unaryOperators.add(eOperator);
    }
 
    public List< OPERATOR > getUnaryOperators() {
        return this.unaryOperators;
    }
 
    public void setExpression( IExpression expression ) {
        this.expression = expression;
    }
 
    public IExpression getExpression() {
        return this.expression;
    }
}

PostfixUnaryOperatorExpression

This class represents postfix unary operator expression. Only the operators ++ and may be postfix operators. Like the prefix unary operator expression, a list of operators is legal after the expression.

package org.structuredparsing.java15grammar.ast;
 
import java.util.ArrayList;
import java.util.List;
 
public class PostfixUnaryOperatorExpression implements IExpression {
    private List<OPERATOR> postfixOperators;
    private IExpression expression;
 
    public PostfixUnaryOperatorExpression() {
        postfixOperators = new ArrayList< OPERATOR >();
    }
 
    public void addOperator( OPERATOR eOperator ) {
        postfixOperators.add(eOperator);
    }
 
    public List< OPERATOR > getPostfixOperators() {
        return this.postfixOperators;
    }
 
    public void setExpression( IExpression expression ) {
        this.expression = expression;
    }
 
    public IExpression getExpression() {
        return this.expression;
    }
}

CastExpression

This class represent a cast between two types.

package org.structuredparsing.java15grammar.ast;
 
public class CastExpression implements IExpression {
    private IExpression expressionToCast;
    private IPrimitiveType primitiveType;
    private IQualifiedIdentifier qualifiedIdentifier;
 
    public void setPrimitiveType( IPrimitiveType primitiveType ) {
        this.primitiveType = primitiveType;
    }
 
    public IPrimitiveType getPrimitiveType() {
        return this.primitiveType;
    }
 
    public void setQualifiedIdentifier( IQualifiedIdentifier qualifiedIdentifier ) {
        this.qualifiedIdentifier = qualifiedIdentifier;
    }
 
    public IQualifiedIdentifier getQualifiedIdentifier() {
        return this.qualifiedIdentifier;
    }
 
    public void setExpressionToCast( IExpression expressionToCast ) {
        this.expressionToCast = expressionToCast;
    }
 
    public IExpression getExpressionToCast() {
        return this.expressionToCast;
    }
}

PrimitiveType

This hold one of the basic primitive types.

The enum PRIMITIVE_TYPE

package org.structuredparsing.java15grammar.ast;
 
public enum PRIMITIVE_TYPE {
    BYTE, SHORT, INT, LONG, CHAR, FLOAT, DOUBLE, BOOLEAN
}

IPrimitiveType

package org.structuredparsing.java15grammar.ast;
 
public interface IPrimitiveType {
 
    public PRIMITIVE_TYPE getType();
}

PrimitiveType

package org.structuredparsing.java15grammar.ast;
 
public class PrimitiveType implements IPrimitiveType {
    private PRIMITIVE_TYPE primitiveType;
 
    public void setType( PRIMITIVE_TYPE primitiveType ) {
        this.primitiveType = primitiveType;
    }
 
    @Override
    public PRIMITIVE_TYPE getType() {
        return primitiveType;
    }
}

LiteralExpression

LiteralExpression represents a literal. A String object holds the literal content. The enum LITERAL holds the type of literal.

package org.structuredparsing.java15grammar.ast;
 
public enum LITERAL {
    STRING, INTEGER, FLOATING_POINT, CHARACTER, NULL, BOOLEAN_LITERAL
}
package org.structuredparsing.java15grammar.ast;
 
public class LiteralExpression implements IExpression {
    private String literalContent;
    private LITERAL literalType;
 
    public void setLiteralContent( String literlaContent ) {
        this.literalContent = literlaContent;
    }
 
    public String getLiteralContent() {
        return this.literalContent;
    }
 
    public void setLiteralType( LITERAL literalType ) {
        this.literalType = literalType;
    }
 
    public LITERAL getLiteralType() {
        return this.literalType;
    }
}

Next Chapter Grammar Rules - part 8


<- back

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License