Jr BNF

Notation:
* Characters surrounded by apostophes ("'") are literals;
  they shall appear in the production exactly as-is.
* Items in brackets [...] means zero-or-one of the item.
* Items followed by an asterisk (*) means zero-or-more of the item.
* Items followed by a plus (+) mean one-or-more of the item.
* Parentheses are used to group stuff.  When the production calls for a literal
  parenthesis, we use '(' and ')'.
* Words surrounded by angle brackets <> are variable names and reduce
  to the production "identifier".
* := means "is defined as".
* a|b|c means "a or b or c".
* All nonterminals in this BNF begin with capital letters.
* Begin with the "Program" production.
* Whitespace rules are explained at the bottom of this file.
* Additional semantic rules are listed at the bottom of this file.

Program := NoMethodsApproach |
           MethodsButNoClassApproach |
           ClassApproach

NoMethodsApproach := [ClassDeclarePart] ActionPart

MethodsButNoClassApproach := [ClassDeclarePart] MethodPart

ClassApproach := [ImportPart]
                 ClassCommand
                 ClassRequiredDocPart 
                 [ClassDeclarePart]
                 [Invariant] 
                 [Constructor]  
                 [MethodPart] 
                 EndClassCommand

ClassDeclarePart := ConstantCommand* 
                    ClassBoxDecl*

ConstantCommand := 'Constant' <constantname> '=' Value 'ofType' ScalarPrimitiveType ['is' Visibility]
 RULE: The word 'is' is required if the Program uses the ClassApproach
 RULE: The word 'is' is not allowed if the Program does not use the ClassApproach

ClassBoxDecl := ClassBoxCommand | ClassBoxesCommand

ClassBoxCommand := 'Box' <boxname> Type ['is' Visibility]
 RULE: The word 'is' is required if the Program uses the ClassApproach
 RULE: The word 'is' is not allowed if the Program does not use the ClassApproach

ClassBoxesCommand := 'Boxes' <boxname> (',' <boxname>)+ Type ['are' Visibility]
 RULE: The word 'are' is required if the Program uses the ClassApproach
 RULE: The word 'are' is not allowed if the Program does not use the ClassApproach

ImportPart := ImportCommand*

ImportCommand := 'Import' ImportLib

ImportLib := 'JJIO' | 'JJGUI' | 'JJDBC' | 'JJUtilTime' | 'JJUtil???'

ClassCommand := 'Class' <classname>

EndClassCommand := 'EndClass' <classname>
 RULE: The classname shall exactly match the classname supplied on the Class command
 RULE: The classname shall match exactly the classname supplied on the ClassCommand

ClassRequiredDocPart := '-- Name:' <username> |
                        '--Name:' <username>

Invariant := InvariantCommand
             CheckCommand*
             EndInvariantCommand

InvariantCommand := 'Invariant'

EndInvariantCommand := 'EndInvariant'
 RULE: The word 'EndInvariant' shall begin in the same column as its matching 'Invariant'.

CheckCommand := 'Check' ScalarBoolExpr 'bounce' StringLiteral 

Constructor := ConstructorCommand
               SlotCommand*
               LocalBoxDecl*
               [ActionPart]
               EndConstructorCommand

ConstructorCommand := 'Constructor' <classname>  '(' SlotDeclList ')' 'is' 'public'
 RULE: The classname shall match exactly the classname supplied on the ClassCommand

EndConstructorCommand := 'EndConstructor' <classname>
 RULE: The word 'EndConstructor' shall begin in the same column as its matching 'Constructor'.
 RULE: The classname shall match exactly the classname supplied on the ClassCommand

LocalBoxDecl := LocalBoxCommand | LocalBoxesCommand

LocalBoxCommand := 'Box' <boxname> Type

LocalBoxesCommand := 'Boxes' <boxname> (',' <boxname>)+ Type

# routines and functions

MethodPart := (Routine | Function)+

Routine := RoutineCommand
           SlotCommand*
           LocalBoxDecl*
           [StartCommand]
           PreCheckCommand*
           [ActionPart]
           PostCheckCommand*
           EndRoutineCommand

RoutineCommand := 'Routine' <routinename> '(' SlotDeclList ')' 'is' Visibility
 RULE: The word 'is' is required if the Program uses the ClassApproach
 RULE: The word 'is' is not allowed if the Program does not use the ClassApproach

EndRoutineCommand := 'EndRoutine' <routinename>
 RULE: The word 'EndRoutine' shall begin in the same column as its matching 'Routine'.
 RULE: The routinename shall match exactly the routinename supplied on the RoutineCommand

StartCommand := 'Start'
 RULE: The Start command can only appear once in a class.
 RULE: A Start command can only appear in a public routine with no slots.

Function := FunctionCommand
            SlotCommand*
            ResultBoxDecl*
            LocalBoxDecl*
            PreCheckCommand*
            ActionPart
            PostCheckCommand*
            EndFunctionCommand
 RULE: A function shall set a value in its result box.

FunctionCommand := 'Function' <functionname> Type '(' SlotDeclList ')' 'is' Visibility
 RULE: The word 'is' is required if the Program uses the ClassApproach
 RULE: The word 'is' is not allowed if the Program does not use the ClassApproach

EndFunctionCommand := 'EndFunction' <functionname>
 RULE: The word 'EndFunction' shall begin in the same column as its matching 'Function'.
 RULE: The functionname shall match exactly the functionname supplied on the FunctionCommand

PreCheckCommand := 'PreCheck' ScalarBoolExpr 'bounce' StringLiteral 

PostCheckCommand := 'PostCheck' ScalarBoolExpr 'bounce' StringLiteral 

SlotDeclList := 'none' | 
                <slotname> (',' <slotname>)*

SlotCallList := Expr (',' Expr)*

SlotCommand := 'Slot' <slotname> Type

ResultBoxDecl := 'Box' 'result' Type

OfTypeOrClass := 'ofType' PrimitiveTypeCategory | 
                 'ofClass' ClassTypeCategory

ScalarOfTypeOrClass := 'ofType' ScalarPrimitiveType | 
                       'ofClass' ScalarClassType

PrimitiveTypeCategory := ScalarPrimitiveType | ArrayPrimitiveType

ScalarPrimitiveType := 'int' | 'real' | 'bool'

ArrayPrimitiveType := 'int[]' | 'real[]' | 'bool[]'

ClassTypeCategory := ScalarClassType | ArrayClassType

ScalarClassType := 'Str' | <classname>

ArrayClassType := 'Str[]' | <classname>'[]'

ScalarType := ScalarPrimitiveType | ScalarClassType

ArrayType := ArrayPrimitiveType | ArrayClassType

Visibility := 'public' | 'private'

Value := NumericLiteral | StringLiteral | BoolLiteral

StringLiteral := "Char*"

Char := any printable character

NumericLiteral := IntLiteral | RealLiteral

IntLiteral := Digit+

BoolLiteral := 'true' | 'false'

RealLiteral := Digit+ '.' Digit+

Identifier := Letter (Alphanumeric | '_')*
 RULE: An identifier cannot end with a '_'

Letter := A-Z | a-z

Digit := 0-9

Alphanumeric := Letter | Digit

ArrayMember := <arrayname> '[' ScalarIntExpr ']'

Expr := Expr BinaryBoolOp Expr | 
        Expr BinaryAddOp Expr | 
        Expr BinaryMinusOp Expr | 
        Expr BinaryMultDivOp Expr | 
        Expr BinaryModOp Expr | 
        '(' Expr BinaryRelOp Expr ')' | 
        UnaryBoolOp Expr | 
        UnaryMinusOp Expr | 
        FunctionReference | 
        ArrayMember |
        ClassMember |
        Boxname |
        Value |
        '(' Expr ')'

 RULE: The Expr before and after the BinaryBoolOp shall be of type bool.
 RULE: The Expr before and after the BinaryAddOp shall be of the same type and
 of type int, real or Str.
 RULE: The Expr before and after the BinaryMinusOp shall be of the same type and
 of type int or real.
 RULE: The Expr before and after the BinaryMultDivOp shall be of the same type and
 of type int or real.
 RULE: The Expr before and after the BinaryModOp shall be of type int.
 RULE: The Expr before and after the BinaryRelOp shall be of the same type and
 of type int or real.
 RULE: The Expr after a UnaryBoolOp shall be of type bool.
 RULE: The Expr after a UnaryMinusOp shall be of type int or real.

ScalarIntExpr := Expr
 RULE: A ScalarIntExpr shall be of type int

ScalarBoolExpr := Expr
 RULE: A ScalarBoolExpr shall be of type bool

ScalarStrExpr := Expr
 RULE: A ScalarStrExpr shall be of class Str

LhsExpr := ArrayMember |
           Boxname

Boxname := <boxname>
 RULE: Unless being used in a SlotCallList, the type of the boxname shall be 
 of type ScalarType.

ClassMember := <classboxname>.<boxname>

BinaryBoolOp := 'and' | 'or'

BinaryAddOp := '+'

BinaryMinusOp := '-'

BinaryMultDivOp := '*' | '/'

BinaryModOp := '%'

BinaryRelOp := '<' | '<=' | '>' | '>=' | '==' | '!='

UnaryBoolOp := 'not'

UnaryMinusOp := '-'

ActionPart := (Construct | ActionCommand)+

Construct := IfConstruct | LoopConstruct

ActionCommand := SetCommand |
                 CallCommand |
                 NewArrayCommand |
                 NewCommand |
                 InputCommand |
                 OutputCommand |
                 OutputlnCommand |
                 DebugCommand |
                 DebuglnCommand |
                 TryCall Command |
                 TrySet Command |
                 CheckCommand

IfConstruct := IfPart
               [ActionPart]
               ElseIfPart*
               [ElsePart]
               EndIfCommand

IfPart := IfCommand
          [ActionPart]

IfCommand := 'If' ScalarBoolExpr 'then'
 RULE: If the IfCommand is nested within an outer IfConstruct, the word 'If'
 shall not begin in the same column as the word 'If' from the outer IfConstruct

EndIfCommand := 'EndIf'
 RULE: The word 'EndIf' shall begin in the same column as its matching 'If'.

ElseIfPart := ElseIfCommand
              [ActionPart]

ElseIfCommand := 'ElseIf' ScalarBoolExpr 'then'
 RULE: The word 'ElseIf' shall begin in the same column as its matching 'If'.

ElsePart :=	ElseCommand
		[ActionPart]

ElseCommand := 'Else'
 RULE: The word 'Else' shall begin in the same column as its matching 'If'.

LoopConstruct := RepeatCommand
                 [ActionPart]
                 ExitOnCommand
                 [ActionPart]
                 EndRepeatCommand

RepeatCommand := 'Repeat'
 RULE: If the RepeatCommand is nested within an outer RepeatConstruct, the word 'Repeat'
 shall not begin in the same column as the word 'Repeat' from the outer RepeatConstruct

ExitOnCommand := 'ExitOn' ScalarBoolExpr
 RULE: The word 'ExitOn' shall begin in the same column as its matching 'Repeat'.

EndRepeatCommand := 'EndRepeat'
 RULE: The word 'EndRepeat' shall begin in the same column as its matching 'Repeat'.

SetCommand := 'Set' Assignment

Assignment := LhsExpr '=' Expr
 RULE: The LhsExpr and the Expr shall be of the same type.

 RULE: If the LhsExpr is of type ArrayType, the Expr shall be a
 FunctionReference (or a FunctionReference inside parentheses) of type ArrayType.

CallCommand := 'Call' RoutineReference

RoutineReference := LocalRoutineReference | ClassPublicRoutineReference

LocalRoutineReference := <routinename> [WithSlots]
 RULE: If the routinename is declared with any slots, the WithSlots production
 shall exist.

ClassPublicRoutineReference := <classboxname>.<routinename> [WithSlots]
 RULE: If the routinename is declared with any slots, the WithSlots production
 shall exist.

WithSlots := 'with' '(' SlotCallList ')'

FunctionReference := LocalFunctionReference |
                     ClassPublicFunctionReference |
                     IntrinsicFunctionReference

LocalFunctionReference := <functionname> '(' [SlotCallList] ')'
 RULE: If the functionname is declared with any slots, the SlotCallList production
 shall exist.

ClassPublicFunctionReference := <classboxname>.<functionname> '(' [SlotCallList] ')'
 RULE: If the functionname is declared with any slots, the SlotCallList production
 shall exist.

IntrinsicFunctionReference := <intrinsicfunctionname> '(' SlotCallList ')'

NewArrayCommand := 'NewArray' <arrayname> ScalarOfTypeOrClass '[' ScalarIntExpr ']'

NewCommand := 'New' LhsExpr 'ofClass' ScalarClassType [WithSlots]
 RULE: If the constructor for the classname is declared with any slots,
 the WithSlots production shall exist.

InputCommand := 'Input' <varname>

OutputCommand := 'Output' Expr
 RULE: The Expr shall be of type ScalarType

OutputlnCommand := 'Outputln' Expr
 RULE: The Expr shall be of type ScalarType

DebugCommand := 'Debug' Expr
 RULE: The Expr shall be of type ScalarType

DebuglnCommand := 'Debugln' Expr
 RULE: The Expr shall be of type ScalarType

TryCallCommand := 'TryCall' FileIORoutineReference 'OnFail' RoutineReferenceOrAssignment

FileIORoutineReference := ClassPublicRoutineReference

TrySetCommand := 'TrySet' StringConversionAssignment 'OnFail' RoutineReferenceOrAssignment

StringConversionAssignment := <boxname> '=' StringConversionFunctionReference
 RULE: The boxname shall be the same type as the StringConversionFunctionReference.

StringConversionFunctionReference := 'StringToInt' '(' ScalarStrExpr ')' |
                                     'StringToReal' '(' ScalarStrExpr ')'

RoutineReferenceOrAssignment := RoutineReference | Assignment


-----------------------------------------------------------------------------------
Semantic Rules:
1. Types.
  Jr is a strongly-typed language.  No automatic type conversions will be 
  performed.

2. Names.
  Variable names in Jr shall be alphanumeric, but may not begin with an 
  underscore.  There is no built-in limit on how long names may be.

3. StringLiteral.
  Any printable character may be in a StringLiteral.

4. Whitespace.
  Whitespace is required between all tokens.  The first word of a Command shall
  be the first word on a line.

5. Initialization.
  Variables are not automatically initialized. All variables shall be explicitly
  set before being used in an Expr or a SlotCallList.

6. Operator Precedence.
  The precedence of operators is the same as the equivalent operators in Java.
        Highest:

        Lowest:

-----------------------------------------------------------------------------------
Appendix A: Commands, in the order that they appear in this BNF ...

 ConstantCommand := 'Constant' <constantname> '=' Value 'ofType' ScalarPrimitiveType ['is' Visibility]
 ClassBoxCommand := 'Box' <boxname> Type ['is' Visibility]
 ClassBoxesCommand := 'Boxes' <boxname> (',' <boxname>)+ Type ['are' Visibility]
 ImportCommand := 'Import' ImportLib
 ClassCommand := 'Class' <classname>
 EndClassCommand := 'EndClass' <classname>
 InvariantCommand := 'Invariant'
 EndInvariantCommand := 'EndInvariant'
 CheckCommand := 'Check' ScalarBoolExpr 'bounce' StringLiteral 
 ConstructorCommand := 'Constructor' <classname>  '(' SlotDeclList ')' 'is' 'public'
 EndConstructorCommand := 'EndConstructor' <classname>
 LocalBoxCommand := 'Box' <boxname> Type
 LocalBoxesCommand := 'Boxes' <boxname> (',' <boxname>)+ Type
 RoutineCommand := 'Routine' <routinename> '(' SlotDeclList ')' ['is' Visibility]
 EndRoutineCommand := 'EndRoutine' <routinename>
 StartCommand := 'Start'
 FunctionCommand := 'Function' <functionname> Type '(' SlotDeclList ')' ['is' Visibility]
 EndFunctionCommand := 'EndFunction' <functionname>
 PreCheckCommand := 'PreCheck' ScalarBoolExpr 'bounce' StringLiteral 
 PostCheckCommand := 'PostCheck' ScalarBoolExpr 'bounce' StringLiteral 
 SlotCommand := 'Slot' <slotname> Type
 IfCommand := 'If' ScalarBoolExpr 'then'
 EndIfCommand := 'EndIf'
 ElseIfCommand := 'ElseIf' ScalarBoolExpr 'then'
 ElseCommand := 'Else'
 RepeatCommand := 'Repeat'
 ExitOnCommand := 'ExitOn' ScalarBoolExpr
 EndRepeatCommand := 'EndRepeat'
 SetCommand := 'Set' Assignment
 CallCommand := 'Call' RoutineReference
 NewArrayCommand := 'NewArray' <arrayname> ScalarOfTypeOrClass '[' ScalarIntExpr ']'
 NewCommand := 'New' LhsExpr 'ofClass' ScalarClassType [WithSlots]
 InputCommand := 'Input' <varname>
 OutputCommand := 'Output' Expr
 OutputlnCommand := 'Outputln' Expr
 DebugCommand := 'Debug' Expr
 DebuglnCommand := 'Debugln' Expr
 TryCallCommand := 'TryCall' FileIORoutineReference 'OnFail' RoutineReferenceOrAssignment
 TrySetCommand := 'TrySet' StringConversionAssignment 'OnFail' RoutineReferenceOrAssignment