// Copyright (c) 2007-2010 by Kavanagh Consultancy Limited. All rights reserved.
// This pattern file defines the syntax and lexical rules for Action Language code in BridgePoint 4.2 onwards
// References:
// [BPAL97] 'BridgePoint(r) 3.3 Action Langage Manual', Project Technology, 1997. (on CD supplied with [Starr01])
// [Starr01] Leon Starr: 'Executable UML: A Case Study', Model Integration, 2001. ISBN 0-9708044-0-7
// [OAL02] 'Object Action Language(tm) Manual - Document Version: 1.4', Project Technology, 2002.
// [OAL08] 'Object Action Language Reference Manual', Mentor Graphics, 2008.
ObjectActionLanguage : // Syntax Rules
code := statementBlock
statementBlock := { statement ';' }*
statement := ifBlock
| forEachBlock
| whileBlock
| breakStatement
| continueStatement
| controlStopStatement
| createObjectStatement
| deleteObjectStatement
| selectFromStatement
| relateStatement
| unrelateStatement
| selectRelatedByStatement
| generateStatement
| createEventStatement
| invokeStatement
| returnStatement
| assignStatement
// Control Structures
// Parentheses around control structure conditions are strongly recommended but not required
ifBlock := IF booleanExpression
statementBlock
{ ELIF booleanExpression
statementBlock }*
[ ELSE
statementBlock ]
END IF
forEachBlock := FOR EACH variable IN variable
statementBlock
END FOR
whileBlock := WHILE booleanExpression
statementBlock
END WHILE
breakStatement := BREAK
continueStatement := CONTINUE
// BPAL97 defines control stop statement but OAL02 drops it completely
controlStopStatement := CONTROL STOP
// Objects
createObjectStatement := CREATE OBJECT INSTANCE [ variable ] OF objectKeyLetters
deleteObjectStatement := DELETE OBJECT INSTANCE variable
selectFromStatement := SELECT ( ANY | MANY ) variable FROM INSTANCES OF objectKeyLetters [ whereClause ]
whereClause := WHERE booleanExpression
// Relationships
relateStatement := RELATE variableOrSelf TO variableOrSelf
ACROSS relationshipSpecification [ USING variableOrSelf ]
relationshipSpecification := relationshipID [ '.' verbPhrase ]
unrelateStatement := UNRELATE variableOrSelf FROM variableOrSelf
ACROSS relationshipSpecification [ USING variableOrSelf ]
selectRelatedByStatement := SELECT ( ONE | ANY | MANY ) variable RELATED BY instanceChain [ whereClause ]
instanceChain := variableOrSelf { "->" objectKeyLetters '[' relationshipSpecification ']' }+
// Events
// OAL08 adds attribute access as generate target
generateStatement := GENERATE ( eventSpecification | variableAccess | attributeAccess )
// BPAL97 uses the ASSIGNER keyword as a suffix below while OAL02 uses the CLASS keyword instead
eventSpecification := eventLabel [ ':' eventMeaning ]
[ '(' [ eventDataItem ':' expression { ',' eventDataItem ':' expression }* ] ')' ]
TO ( objectKeyLetters ( CREATOR | ASSIGNER | CLASS ) | terminatorKeyLetters | variableOrSelf )
createEventStatement := CREATE EVENT INSTANCE variable OF eventSpecification
// Operations
invokeStatement := ( [ TRANSFORM [ assignTarget ] ] objectKeyLetters "::"
| [ BRIDGE [ assignTarget ] ] terminatorKeyLetters "::"
| "::" | variableOrSelf '.' )
operation '(' [ parameter ':' expression { ',' parameter ':' expression }* ] ')'
returnStatement := RETURN [ expression ]
// Variables
// OAL08 drops event data item access as assign target
assignStatement := [ ASSIGN ] ( assignTarget | eventDataItemAccess '=' ) expression
// OAL08 adds parameter access as assign target
assignTarget := ( variableAccess | attributeAccess | parameterAccess ) '='
// Expressions
booleanExpression := expression
expression := logicalOrExpression
logicalOrExpression := logicalAndExpression { OR logicalAndExpression }*
logicalAndExpression := comparisonExpression { AND comparisonExpression }*
comparisonExpression := addExpression [ ( "==" | "!=" | '<' | "<=" | '>' | ">=" ) addExpression ]
addExpression := multiplyExpression { ( '+' | '-' ) multiplyExpression }*
multiplyExpression := unaryExpression { ( '*' | '/' | '%' ) unaryExpression }*
unaryExpression := [ NOT | '+' | '-' ] term
term := ( EMPTY | NOT_EMPTY | CARDINALITY ) variable
| readValue | invokeExpression | '(' ( [ assignTarget ] expression ) ')'
readValue := literalValue | variableAccess | attributeAccess | eventDataItemAccess | parameterAccess | '?'
// OAL08 adds enumerated literals
literalValue := booleanLiteral | enumeratedLiteral | stringLiteral | integerLiteral | realLiteral
booleanLiteral := TRUE | FALSE
enumeratedLiteral := enumeratedType "::" legalValue ! '('
variableAccess := variableSelfOrSelected ! '.'
variableSelfOrSelected := variableOrSelf | SELECTED
variableOrSelf := variable | SELF
attributeAccess := variableSelfOrSelected '.' attribute ! '('
// OAL08 adds array element indexing and nested attribute access
// attributeAccess := variableSelfOrSelected '[' expression ']'
// | variableSelfOrSelected [ '[' expression ']' ] { '.' attribute [ '[' expression ']' ] }+
eventDataItemAccess := RCVD_EVT '.' eventDataItem
parameterAccess := PARAM '.' parameter
invokeExpression := ( [ TRANSFORM ] objectKeyLetters "::"
| [ BRIDGE ] terminatorKeyLetters "::"
| "::" | variableSelfOrSelected '.' )
operation '(' [ parameter ':' expression { ',' parameter ':' expression }* ] ')'
// External References
objectKeyLetters := constrainedName
attribute := name // Names after '.' are not treated as keywords
// OAL08 allows constrained name as verb phrase
verbPhrase := unconstrainedName | constrainedName
enumeratedType := constrainedName
legalValue := constrainedName
// OAL08 adds '*' suffix for polymorphic event labels
eventLabel := constrainedName [ '*' ]
eventMeaning := unconstrainedName | constrainedName
eventDataItem := name // Names after '.' and before ':' are not treated as keywords
terminatorKeyLetters := constrainedName
operation := constrainedName
parameter := name // Names after '.' and before ':' are not treated as keywords
variable := constrainedName
ObjectActionLanguage :: // Lexical Rules
input := { $javaWhitespace | comment | token }*
comment := "//" { ! '\n' $anyCharacter }* $endOfLine
token := name | unconstrainedName | stringLiteral | integerLiteral | realLiteral | separatorOrOperator
name ::= nameStart { namePart }*
nameStart := 'a'..'z' | 'A'..'Z' | '_' | '#'
namePart := 'a'..'z' | 'A'..'Z' | '0'..'9' | '_' | '#'
unconstrainedName ::= '\'' { ! '\n' ! '\'' $anyCharacter }+ '\''
stringLiteral ::= '"' { ! '\n' ! '"' $anyCharacter }* '"'
integerLiteral ::= [ '-' ] { '0'..'9' }+ ! '.'
realLiteral ::= [ '-' ] { '0'..'9' }+ '.' { '0'..'9' }+
separatorOrOperator ::= "!=" | "->" | "::" | "<=" | "==" | ">=" | '%' | '(' | ')' | '*' | '+' | ','
| '-' | '.' | '/' | ':' | ';' | '<' | '=' | '>' | '?' | '[' | ']'
// Special Name Tokens
constrainedName ::= name && ! keyword
// OAL02 adds CLASS keyword and drops CONTROL and STOP keywords
// OAL08 adds SEND and SENDER keywords
keyword := ACROSS | AND | ANY | ASSIGN | ASSIGNER
| BREAK | BRIDGE | BY
| CARDINALITY | CLASS | CONTINUE | CONTROL | CREATE | CREATOR
| DELETE
| EACH | ELIF | ELSE | EMPTY | END | EVENT
| FALSE | FOR | FROM
| GENERATE
| IF | IN | INSTANCE | INSTANCES
| MANY
| NOT | NOT_EMPTY
| OBJECT | OF | ONE | OR
| PARAM
| RCVD_EVT | RELATE | RELATED | RETURN
| SELECT | SELECTED | SELF | SEND | SENDER | STOP
| TO | TRANSFORM | TRUE
| UNRELATE | USING
| WHERE | WHILE
ACROSS ::= ( "across" | "ACROSS" | "Across" ) ! namePart
AND ::= ( "and" | "AND" | "And" ) ! namePart
ANY ::= ( "any" | "ANY" | "Any" ) ! namePart
ASSIGN ::= ( "assign" | "ASSIGN" | "Assign" ) ! namePart
ASSIGNER ::= ( "assigner" | "ASSIGNER" | "Assigner" ) ! namePart
BREAK ::= ( "break" | "BREAK" | "Break" ) ! namePart
BRIDGE ::= ( "bridge" | "BRIDGE" | "Bridge" ) ! namePart
BY ::= ( "by" | "BY" | "By" ) ! namePart
CARDINALITY ::= ( "cardinality" | "CARDINALITY" | "Cardinality" ) ! namePart
CLASS ::= ( "class" | "CLASS" | "Class" ) ! namePart
CONTINUE ::= ( "continue" | "CONTINUE" | "Continue" ) ! namePart
CONTROL ::= ( "control" | "CONTROL" | "Control" ) ! namePart
CREATE ::= ( "create" | "CREATE" | "Create" ) ! namePart
CREATOR ::= ( "creator" | "CREATOR" | "Creator" ) ! namePart
DELETE ::= ( "delete" | "DELETE" | "Delete" ) ! namePart
EACH ::= ( "each" | "EACH" | "Each" ) ! namePart
ELIF ::= ( "elif" | "ELIF" | "Elif" ) ! namePart
ELSE ::= ( "else" | "ELSE" | "Else" ) ! namePart
EMPTY ::= ( "empty" | "EMPTY" | "Empty" ) ! namePart
END ::= ( "end" | "END" | "End" ) ! namePart
EVENT ::= ( "event" | "EVENT" | "Event" ) ! namePart
FALSE ::= ( "false" | "FALSE" | "False" ) ! namePart
FOR ::= ( "for" | "FOR" | "For" ) ! namePart
FROM ::= ( "from" | "FROM" | "From" ) ! namePart
GENERATE ::= ( "generate" | "GENERATE" | "Generate" ) ! namePart
IF ::= ( "if" | "IF" | "If" ) ! namePart
IN ::= ( "in" | "IN" | "In" ) ! namePart
INSTANCE ::= ( "instance" | "INSTANCE" | "Instance" ) ! namePart
INSTANCES ::= ( "instances" | "INSTANCES" | "Instances" ) ! namePart
MANY ::= ( "many" | "MANY" | "Many" ) ! namePart
NOT ::= ( "not" | "NOT" | "Not" ) ! namePart
NOT_EMPTY ::= ( "not_empty" | "NOT_EMPTY" | "Not_empty" ) ! namePart
OBJECT ::= ( "object" | "OBJECT" | "Object" ) ! namePart
OF ::= ( "of" | "OF" | "Of" ) ! namePart
ONE ::= ( "one" | "ONE" | "One" ) ! namePart
OR ::= ( "or" | "OR" | "Or" ) ! namePart
PARAM ::= ( "param" | "PARAM" | "Param" ) ! namePart
RCVD_EVT ::= ( "rcvd_evt" | "RCVD_EVT" | "Rcvd_evt" ) ! namePart
RELATE ::= ( "relate" | "RELATE" | "Relate" ) ! namePart
RELATED ::= ( "related" | "RELATED" | "Related" ) ! namePart
RETURN ::= ( "return" | "RETURN" | "Return" ) ! namePart
SELECT ::= ( "select" | "SELECT" | "Select" ) ! namePart
SELECTED ::= ( "selected" | "SELECTED" | "Selected" ) ! namePart
SELF ::= ( "self" | "SELF" | "Self" ) ! namePart
SEND ::= ( "send" | "SEND" | "Send" ) ! namePart
SENDER ::= ( "sender" | "SENDER" | "Sender" ) ! namePart
STOP ::= ( "stop" | "STOP" | "Stop" ) ! namePart
TO ::= ( "to" | "TO" | "To" ) ! namePart
TRANSFORM ::= ( "transform" | "TRANSFORM" | "Transform" ) ! namePart
TRUE ::= ( "true" | "TRUE" | "True" ) ! namePart
UNRELATE ::= ( "unrelate" | "UNRELATE" | "Unrelate" ) ! namePart
USING ::= ( "using" | "USING" | "Using" ) ! namePart
WHERE ::= ( "where" | "WHERE" | "Where" ) ! namePart
WHILE ::= ( "while" | "WHILE" | "While" ) ! namePart
relationshipID ::= ( 'R' | 'r' ) positiveInteger
positiveInteger ::= '1'..'9' { '0'..'9' }* ! namePart
// End of File