// 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