From 27557489c576b43c223ec356a81c91c93a2b3533 Mon Sep 17 00:00:00 2001 From: Christian Weich Date: Thu, 19 Sep 2024 13:11:59 +0200 Subject: [PATCH 1/2] Upgrade arden grammar to Arden syntax 3.0 R2 specification --- arden/ArdenLexer.g4 | 222 ++- arden/ArdenParser.g4 | 1116 +++++------- arden/README.md | 2 +- arden/desc.xml | 3 +- arden/examples/Contraindication Alert.mlm | 45 + .../{First.mlm => Data Interpretation.mlm} | 26 +- arden/examples/Fourth.mlm | 237 --- .../MLM Fever Calculation - Crisp.mlm | 46 + .../MLM Fever Calculation - Fuzzy Logic.mlm | 44 + ...M Fever Calculation - Fuzzy Simulation.mlm | 50 + arden/examples/MLM Translated from CARE.mlm | 88 + arden/examples/MLM Using While Loop.mlm | 64 + ...ifth.mlm => MLM for Doses Calculation.mlm} | 4 +- .../Management Suggestion Gentamicin.mlm | 77 + ...Management Suggestion Granulocytopenia.mlm | 58 + arden/examples/Monitoring.mlm | 69 + ...econd.mlm => Research Study Screening.mlm} | 60 +- arden/examples/SyntaxTest.mlm | 1496 +++++++++++++++++ arden/examples/Third.mlm | 190 --- arden/pom.xml | 12 +- pom.xml | 1 + 21 files changed, 2578 insertions(+), 1332 deletions(-) create mode 100644 arden/examples/Contraindication Alert.mlm rename arden/examples/{First.mlm => Data Interpretation.mlm} (83%) delete mode 100644 arden/examples/Fourth.mlm create mode 100644 arden/examples/MLM Fever Calculation - Crisp.mlm create mode 100644 arden/examples/MLM Fever Calculation - Fuzzy Logic.mlm create mode 100644 arden/examples/MLM Fever Calculation - Fuzzy Simulation.mlm create mode 100644 arden/examples/MLM Translated from CARE.mlm create mode 100644 arden/examples/MLM Using While Loop.mlm rename arden/examples/{Fifth.mlm => MLM for Doses Calculation.mlm} (92%) create mode 100644 arden/examples/Management Suggestion Gentamicin.mlm create mode 100644 arden/examples/Management Suggestion Granulocytopenia.mlm create mode 100644 arden/examples/Monitoring.mlm rename arden/examples/{Second.mlm => Research Study Screening.mlm} (68%) create mode 100644 arden/examples/SyntaxTest.mlm delete mode 100644 arden/examples/Third.mlm diff --git a/arden/ArdenLexer.g4 b/arden/ArdenLexer.g4 index c60b0a820c..a30383c6e9 100644 --- a/arden/ArdenLexer.g4 +++ b/arden/ArdenLexer.g4 @@ -1,15 +1,10 @@ -// $antlr-format alignTrailingComments true, columnLimit 150, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine true, allowShortBlocksOnASingleLine true, minEmptyLines 0, alignSemicolons ownLine -// $antlr-format alignColons trailing, singleLineOverrulesHangingColon true, alignLexerCommands true, alignLabels true, alignTrailers true - lexer grammar ArdenLexer; -options { - caseInsensitive = true; -} + +options { caseInsensitive = true; } // Keywords ABS : 'abs'; -ACTION : 'action:'; +ACTION : 'action'; ADD : 'add'; AFTER : 'after'; AGGREGATE : 'aggregate'; @@ -21,15 +16,15 @@ APPLICABILITY : 'applicability'; ARCCOS : 'arccos'; ARCSIN : 'arcsin'; ARCTAN : 'arctan'; -ARDEN : 'arden:'; -ARDEN_VERSION : 'version ' ('2' ('.' ( '1' | '2' | '5' | '6' | '7' | '8' | '9' | '10'))? | '3'); +ARDEN : 'arden'; +ARDEN_VERSION : 'version 3'; ARETRUE : 'aretrue'; ARGUMENT : 'argument'; AS : 'as'; AT : 'at'; ATTIME : 'attime'; ATTRIBUTE : 'attribute'; -AUTHOR : 'author:' -> mode(TextMode); +AUTHOR : 'author' -> mode(TextMode); AVERAGE : 'average' | 'avg'; BE : 'be'; BEFORE : 'before'; @@ -40,20 +35,19 @@ CALL : 'call'; CASE : 'case'; CEILING : 'ceiling'; CHARACTERS : 'characters'; -CITATIONS : 'citations:'; +CITATIONS : 'citations' -> mode(TextMode); CLONE : 'clone'; CONCLUDE : 'conclude'; COSINE : 'cos' 'ine'?; COUNT : 'count'; CRISP : 'crisp'; CURRENTTIME : 'currenttime'; -DATA : 'data:'; -DATAWC : 'data'; -DATE : 'date:'; +DATA : 'data'; +DATE : 'date'; DAY : 'day' 's'?; DECREASE : 'decrease'; DEFAULT : 'default'; -DEFAULTCO : 'default:' -> mode(TwoCharMode); +DEFAULT_SLOT : DEFAULT COLON -> mode(TwoCharMode); DEFUZZIFIED : 'defuzzified'; DELAY : 'delay'; DESTINATION : 'destination'; @@ -63,7 +57,7 @@ EARLIEST : 'earliest'; ELEMENTS : 'elements'; ELSE : 'else'; ELSEIF : 'elseif'; -END : 'end:'; +END : 'end'; ENDDO : 'enddo'; ENDIF : 'endif'; ENDSWITCH : 'endswitch'; @@ -71,13 +65,13 @@ EQUAL : 'equal'; EVENT : 'event'; EVENTTIME : 'eventtime'; EVERY : 'every'; -EVOKE : 'evoke:'; +EVOKE : 'evoke'; EXIST : 'exist' 's'?; EXP : 'exp'; -EXPLANATION : 'explanation:' -> mode(TextMode); +EXPLANATION : 'explanation' -> mode(TextMode); EXTRACT : 'extract'; FALSE : 'false'; -FILENAME : 'filename:' -> mode(MlmName); +FILENAME : 'filename' -> mode(MlmName); FIND : 'find'; FIRST : 'first'; FLOOR : 'floor'; @@ -94,8 +88,8 @@ IN : 'in'; INCLUDE : 'include'; INCREASE : 'increase'; INDEX : 'index'; -INSTITUTION : 'institution:' -> mode(TextMode); -INSTITUTIONWC : 'institution'; +INSTITUTION : 'institution'; +INSTITUTION_SLOT: INSTITUTION COLON -> mode(TextMode); INT : 'int'; INTERFACE : 'interface'; INTERVAL : 'interval'; @@ -103,8 +97,8 @@ IS : 'is' | 'are' | 'was' | 'were'; ISTRUE : 'istrue'; IT : 'it' | 'they'; KEYWORDS : 'keywords' -> mode(TextMode); -KNOWLEDGE : 'knowledge:'; -LANGUAGE : 'language:' -> mode(TwoCharMode); +KNOWLEDGE : 'knowledge'; +LANGUAGE : 'language' -> mode(TwoCharMode); LAST : 'last'; LATEST : 'latest'; LEAST : 'least'; @@ -112,17 +106,17 @@ LEFT : 'left'; LENGTH : 'length'; LESS : 'less'; LET : 'let'; -LIBRARY : 'library:'; +LIBRARY : 'library'; LINGUISTIC : 'linguistic'; -LINKS : 'links:'; +LINKS : 'links' -> mode(TextMode); LINK_TYPE : 'url_link' | 'mesh_link' | 'other_link' | 'exe_link'; LIST : 'list'; LOCALIZED : 'localized'; LOG10 : 'log10'; LOG : 'log'; -LOGIC : 'logic:'; +LOGIC : 'logic'; LOWERCASE : 'lowercase'; -MAINTENANCE : 'maintenance:'; +MAINTENANCE : 'maintenance'; MATCHES : 'matches'; MAXIMUM : 'max' 'imum'?; MEDIAN : 'median'; @@ -131,8 +125,8 @@ MESSAGE : 'message'; MINIMUM : 'min' 'imum'?; MINUTE : 'minute' 's'?; MLM : 'mlm'; -MLMNAME : 'mlmname:' -> mode(MlmName); -MLM_SELF : 'mlm' [_-]'self'; +MLMNAME : 'mlmname' -> mode(MlmName); +MLM_SELF : 'mlm'[_-]'self'; MONTH : 'month' 's'?; MOST : 'most'; NAMES : 'names'; @@ -152,12 +146,12 @@ PATTERN : 'pattern'; PERCENT : 'percent' | '%'; PRECEDING : 'preceding'; PRESENT : 'present'; -PRIORITY : 'priority:'; -PURPOSE : 'purpose:' -> mode(TextMode); +PRIORITY : 'priority'; +PURPOSE : 'purpose' -> mode(TextMode); READ : 'read'; REMOVE : 'remove'; REPLACE : 'replace'; -RESOURCES : 'resources:'; +RESOURCES : 'resources'; RETURN : 'return'; REVERSE : 'reverse'; RIGHT : 'right'; @@ -169,7 +163,7 @@ SET : 'set'; SINE : 'sin' 'e'?; SLOPE : 'slope'; SORT : 'sort'; -SPECIALIST : 'specialist:' -> mode(TextMode); +SPECIALIST : 'specialist' -> mode(TextMode); SQRT : 'sqrt'; STARTING : 'starting'; STDDEV : 'stddev'; @@ -184,7 +178,7 @@ THAN : 'than'; THE : 'the' -> channel(HIDDEN); THEN : 'then'; TIME : 'time'; -TITLE : 'title:' -> mode(TextMode); +TITLE : 'title' -> mode(TextMode); TO : 'to'; TODAY : 'today'; TOMORROW : 'tomorrow'; @@ -193,19 +187,19 @@ TRIM : 'trim'; TRUE : 'true'; TRUNCATE : 'truncate'; TRUTHVALUE : 'truth value'; -TYPE : 'type:'; -TYPE_CODE : 'data' [_-]'driven'; +TYPE : 'type'; +TYPE_CODE : 'data'[_-]'driven'; UNTIL : 'until'; UPPERCASE : 'uppercase'; -URGENCY : 'urgency:'; +URGENCY : 'urgency'; USING : 'using'; -VALIDATION : 'validation:'; +VALIDATION : 'validation'; VALIDATION_CODE : 'production' | 'research' | 'testing' | 'expired'; VARIABLE : 'variable'; VARIANCE : 'variance'; -VERSION : 'version:' -> mode(TextMode); +VERSION : 'version' -> mode(TextMode); WEEK : 'week' 's'?; -WEEKDAYLITERAL: +WEEKDAYLITERAL : 'sunday' | 'monday' | 'tuesday' @@ -213,124 +207,106 @@ WEEKDAYLITERAL: | 'thursday' | 'friday' | 'saturday' -; -WHERE : 'where'; -WHILE : 'while'; -WITH : 'with'; -WITHIN : 'within'; -WRITE : 'write'; -YEAR : 'year' 's'?; - -// Seperators -LPAREN : '('; -RPAREN : ')'; -LBRACE : '{' -> mode(DataMapping); -RBRACE : '}'; -LBRACK : '['; -RBRACK : ']'; -SC : ';'; -DSC : ';;'; -COLON : ':'; -DOT : '.'; -COMMA : ','; + ; +WHERE : 'where'; +WHILE : 'while'; +WITH : 'with'; +WITHIN : 'within'; +WRITE : 'write'; +YEAR : 'year' 's'?; + +// Separators +LPAREN : '('; +RPAREN : ')'; +LBRACE : '{' -> mode(DataMapping); +RBRACE : '}'; +LBRACK : '['; +RBRACK : ']'; +SC : ';'; +DSC : ';;'; +COLON : ':'; +DOT : '.'; +COMMA : ','; // Operators -ASSIGN : ':='; -PLUS : '+'; -MINUS : '-'; -MUL : '*'; -DIV : '/'; -POWER : '**'; -EQ : '=' | 'eq'; -LT : '<' | 'lt'; -GT : '>' | 'gt'; -LE : '<=' | 'le'; -GE : '>=' | 'ge'; -NE : '<>' | 'ne'; -DOR : '||'; +ASSIGN : ':='; +PLUS : '+'; +MINUS : '-'; +MUL : '*'; +DIV : '/'; +POWER : '**'; +EQ : '=' | 'eq'; +LT : '<' | 'lt'; +GT : '>' | 'gt'; +LE : '<=' | 'le'; +GE : '>=' | 'ge'; +NE : '<>' | 'ne'; +DOR : '||'; // Digit constructs -NUMBER: Digit+ DOT? Digit* Exponent | DOT Digit+ Exponent; +NUMBER : Digit+ (DOT Digit*)? Exponent? | DOT Digit+ Exponent?; // Date constructs -TIMEOFDAY: Digit Digit COLON Digit Digit Seconds TimeZone; +TIME_OF_DAY : Digit Digit COLON Digit Digit Seconds? TimeZone?; -ISO_DATE: Digit Digit Digit Digit MINUS Digit Digit MINUS Digit Digit; +ISO_DATE : Digit Digit Digit Digit MINUS Digit Digit MINUS Digit Digit; -ISO_DATE_TIME: - Digit Digit Digit Digit MINUS Digit Digit MINUS Digit Digit 't' Digit Digit COLON Digit Digit COLON Digit Digit FractionalDigit TimeZone -; +ISO_DATE_TIME : Digit Digit Digit Digit MINUS Digit Digit MINUS Digit Digit 't' Digit Digit COLON Digit Digit COLON Digit Digit FractionalDigit? TimeZone?; // String constructs -CITATION: Digit+ DOT ' ' ('support' | 'refute')?; +TERM : '\'' .*? '\''; -TERM: '\'' .*? '\''; - -STRING: '"' ( '""' | ~'"')* '"'; +STRING : '"' ( '""' | ~'"' )* '"'; // Creates an identifier with max of 80 chars -IDENTIFIER: - StartIdentifier RestIdentifier RestIdentifier RestIdentifier RestIdentifier RestIdentifier RestIdentifier RestIdentifier -; +IDENTIFIER : Letter ID*; // Comment -COMMENT: '/*' .*? '*/' -> channel(HIDDEN); +COMMENT : '/*' .*? '*/' -> channel(HIDDEN); -LINE_COMMENT: '//' ~[\r\n]* -> channel(HIDDEN); +LINE_COMMENT : '//' ~[\r\n]* -> channel(HIDDEN); // Whitespace -WS: [ \t\r\n]+ -> channel(HIDDEN); +WS : [ \t\r\n]+ -> channel(HIDDEN); + +ERROR : .; // Fragment rules // Digit fragments -fragment Digit: [0-9]; +fragment Digit : [0-9]; -fragment FractionalDigit: (DOT Digit+)?; +fragment FractionalDigit : DOT Digit+; -fragment Exponent: ('e' [+-]? Digit+)?; +fragment Exponent : 'e' [+-]? Digit+; // Date fragments -fragment Seconds: (COLON Digit Digit FractionalDigit)?; +fragment Seconds : COLON Digit Digit FractionalDigit?; -fragment TimeZone: 'z'? | (PLUS | MINUS) Digit Digit COLON Digit Digit; +fragment TimeZone : 'z' | (PLUS | MINUS) Digit Digit COLON Digit Digit; // String fragments -fragment Letter: [a-z]; +fragment Letter : [a-z]; -// Start of the identifier 10 chars, starting with a letter -fragment StartIdentifier: Letter (ID (ID (ID (ID (ID (ID (ID (ID (ID?)?)?)?)?)?)?)?)?)?; - -// Rest of the identifier 10 chars -fragment RestIdentifier: (ID (ID (ID (ID (ID (ID (ID (ID (ID (ID?)?)?)?)?)?)?)?)?)?)?; - -fragment ID: Letter | [0-9] | '_'; - -fragment MlmID: ID | DOT | MINUS; +fragment ID : Letter | Digit | '_'; // Lexer modes mode TextMode; -TEXT: .+? ';;' -> mode(DEFAULT_MODE); +TEXTMODECOLON : ':'; +TEXT : .+?; +UTEXT : ~[;:^]+; +ADSC : ';;' -> mode(DEFAULT_MODE); mode DataMapping; -DATA_MAPPING: (~'}' | '\\' .)+ -> mode(DEFAULT_MODE); +DATA_MAPPING : (~'}' | '\\' .)+ -> mode(DEFAULT_MODE); mode MlmName; -MLMID: - MlmIDStart MlmIDRest MlmIDRest MlmIDRest MlmIDRest MlmIDRest MlmIDRest MlmIDRest -> mode(DEFAULT_MODE) -; +MlMCOLON : ':'; +MLMID : Letter MlmID* -> mode(DEFAULT_MODE); +WS_ID : [ \t\r\n]+ -> channel(HIDDEN); -WS_ID: [ \t\r\n]+ -> channel(HIDDEN); - -fragment MlmIDStart: - Letter (MlmID (MlmID (MlmID (MlmID (MlmID (MlmID (MlmID (MlmID (MlmID?)?)?)?)?)?)?)?)?)? -; -fragment MlmIDRest: - (MlmID (MlmID (MlmID (MlmID (MlmID (MlmID (MlmID (MlmID (MlmID (MlmID?)?)?)?)?)?)?)?)?)?)? -; +fragment MlmID : ID | DOT | MINUS; mode TwoCharMode; -TWOCHARCODE options { - caseInsensitive = false; -}: Letter Letter ('_' [A-Z] [A-Z])? -> mode(DEFAULT_MODE); - -WS_TCM: WS -> channel(HIDDEN); \ No newline at end of file +TWOCHARCOLON : ':'; +TWOCHARCODE options {caseInsensitive = false; }: Letter Letter ('_' [A-Z] [A-Z])? -> mode(DEFAULT_MODE); +WS_TCM : WS -> channel(HIDDEN); \ No newline at end of file diff --git a/arden/ArdenParser.g4 b/arden/ArdenParser.g4 index b5ee4fb53f..ec16ab73f6 100644 --- a/arden/ArdenParser.g4 +++ b/arden/ArdenParser.g4 @@ -30,840 +30,530 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -// $antlr-format alignTrailingComments true, columnLimit 150, minEmptyLines 1, maxEmptyLinesToKeep 1, reflowComments false, useTab false -// $antlr-format allowShortRulesOnASingleLine false, allowShortBlocksOnASingleLine true, alignSemicolons hanging, alignColons hanging - parser grammar ArdenParser; -options { - tokenVocab = ArdenLexer; -} - -// A mlm always consists of three parts and ends with the statement END: - -// These parts are maintenace_category, library_category, knowledge_category Ref: 5.1 - -file_ - : mlms EOF - ; - -mlms - : mlm* - ; +options { tokenVocab = ArdenLexer; } mlm - : maintenanceCategory libraryCategory knowledgeCategory resourcesCategory END - ; -// Maintenace category Ref: 6.1 + : maintenanceCategory libraryCategory knowledgeCategory resourcesCategory END COLON EOF + ; + maintenanceCategory - : MAINTENANCE titleSlot mlmNameSlot ardenVersionSlot versionSlot institutionSlot authorSlot specialistSlot dateSlot validationSlot - ; + : MAINTENANCE COLON titleSlot mlmNameSlot ardenVersionSlot versionSlot institutionSlot authorSlot specialistSlot dateSlot validationSlot + ; -// Library category Ref: 6.2 libraryCategory - : LIBRARY purposeSlot explanationSlot keywordsSlot citationsSlot linksSlot - ; + : LIBRARY COLON purposeSlot explanationSlot keywordsSlot citationsSlot? linksSlot? + ; -// Knowledge category Ref 6.3 knowledgeCategory - : KNOWLEDGE typeSlot dataSlot prioritySlot evokeSlot logicSlot actionSlot urgencySlot - ; + : KNOWLEDGE COLON typeSlot dataSlot prioritySlot? evokeSlot logicSlot actionSlot urgencySlot? + ; -// Resource category Ref: 6.4 resourcesCategory - : (RESOURCES defaultSlot languageSlot)? - ; + : RESOURCES COLON defaultSlot languageSlot+ + ; -// Slots -// Maintenance slots titleSlot - : TITLE TEXT - ; + : TITLE TEXTMODECOLON slotText ADSC + ; + +slotText + : (UTEXT | TEXTMODECOLON | TEXT)+ + ; mlmNameSlot - : (MLMNAME | FILENAME) MLMID DSC - ; + : (MLMNAME | FILENAME) MlMCOLON MLMID DSC + ; ardenVersionSlot - : (ARDEN ARDEN_VERSION DSC)? - ; + : ARDEN COLON ARDEN_VERSION DSC + ; versionSlot - : VERSION TEXT - ; + : VERSION TEXTMODECOLON slotText ADSC + ; institutionSlot - : INSTITUTION TEXT - ; + : INSTITUTION_SLOT slotText ADSC + ; authorSlot - : AUTHOR TEXT - ; + : AUTHOR TEXTMODECOLON slotText ADSC + ; specialistSlot - : SPECIALIST TEXT - ; + : SPECIALIST TEXTMODECOLON slotText ADSC + ; dateSlot - : DATE (ISO_DATE | ISO_DATE_TIME) DSC - ; + : DATE COLON (ISO_DATE | ISO_DATE_TIME) DSC + ; validationSlot - : VALIDATION VALIDATION_CODE DSC - ; + : VALIDATION COLON VALIDATION_CODE DSC + ; -// Library slots purposeSlot - : PURPOSE TEXT - ; + : PURPOSE TEXTMODECOLON slotText ADSC + ; explanationSlot - : EXPLANATION TEXT - ; + : EXPLANATION TEXTMODECOLON slotText ADSC + ; keywordsSlot - : KEYWORDS TEXT - ; + : KEYWORDS TEXTMODECOLON slotText ADSC + ; citationsSlot - : (CITATIONS citationList DSC)? - ; - -citationList - : singleCitation? - | singleCitation SC citationList - ; - -singleCitation - : CITATION? STRING - ; + : CITATIONS TEXTMODECOLON slotText ADSC + ; linksSlot - : (LINKS linkList DSC)? - ; + : LINKS TEXTMODECOLON slotText ADSC + ; -linkList - : singleLink? - | linkList SC singleLink - ; - -singleLink - : (LINK_TYPE TERM)? STRING - ; - -// Knowledge slots typeSlot - : TYPE TYPE_CODE DSC - ; + : TYPE COLON TYPE_CODE DSC + ; dataSlot - : DATA dataBlock DSC - ; + : DATA COLON dataStatement? (SC dataStatement)* SC? DSC + ; prioritySlot - : (PRIORITY NUMBER DSC)? - ; + : PRIORITY COLON NUMBER DSC + ; evokeSlot - : EVOKE evokeBlock DSC - ; + : EVOKE COLON evokeStatement? (SC evokeStatement)* SC? DSC + ; logicSlot - : LOGIC logicBlock DSC - ; + : LOGIC COLON logicStatement? (SC logicStatement)* SC? DSC + ; actionSlot - : ACTION actionBlock DSC - ; + : ACTION COLON actionStatement? (SC actionStatement)* SC? DSC + ; urgencySlot - : (URGENCY (NUMBER | IDENTIFIER) DSC)? - ; + : URGENCY COLON (NUMBER | identifierOrObjectRef) DSC + ; -// Resource slots defaultSlot - : DEFAULTCO TWOCHARCODE DSC - ; + : DEFAULT_SLOT TWOCHARCODE DSC + ; languageSlot - : languageSlot singleLanguageCode - | singleLanguageCode - ; - -singleLanguageCode - : LANGUAGE TWOCHARCODE resourceTerms DSC - ; + : LANGUAGE TWOCHARCOLON TWOCHARCODE (TERM COLON STRING)? (SC TERM COLON STRING)* SC? DSC + ; -resourceTerms - : resourceTerms SC TERM COLON STRING - | (TERM COLON STRING)? - ; - -// Logic block -logicBlock - : logicBlock SC logicStatement - | logicStatement - ; +dataStatement + : identifierBecomes (expr | newObjectPhrase | callPhrase | fuzzySetPhrase) # DataIdentifierOrObjectAssign + | (IDENTIFIER ASSIGN | LET IDENTIFIER BE) dataIdentifierAssign # DataIdentifierAssignPhrase + | (LPAREN dataVarList RPAREN ASSIGN | LET LPAREN dataVarList RPAREN BE) (READ (AS IDENTIFIER)? readPhrase | ARGUMENT | callPhrase) # DataDataVarList + | (fhirObject ASSIGN | LET fhirObject BE) READ AS LATEST? fhirObject fhirReadPhrase? # DataFhir + | IF expr THEN (dataStatement SC)* dataElseIf AGGREGATE? # DataIf + | FOR identifierOrObjectRef IN expr DO (dataStatement SC)* ENDDO # DataFor + | WHILE expr DO (dataStatement SC)* ENDDO # DataWhile + | SWITCH identifierOrObjectRef dataSwitchCases ENDSWITCH AGGREGATE? # DataSwitch + | (timeBecomes | applicabilityBecomes) expr # DataTimeOrApplicabilityAssign + | BREAKLOOP # DataBreakLoop + | INCLUDE IDENTIFIER # DataInclude + ; -logicStatement - : logicAssignment? - | IF logicIfThenElse - | FOR IDENTIFIER IN expr DO logicBlock SC ENDDO - | WHILE expr DO logicBlock SC ENDDO - | logicSwitch - | BREAKLOOP - | CONCLUDE expr - ; - -logicIfThenElse - : expr THEN logicBlock SC logicElseIf - ; +dataElseIf + : ENDIF # DataEndIf + | ELSE (dataStatement SC)* ENDIF # DataElse + | ELSEIF expr THEN (dataStatement SC)* dataElseIf # DataElseIfRecursive + ; -logicElseIf - : ENDIF AGGREGATE? - | ELSE logicBlock SC ENDIF AGGREGATE? - | ELSEIF logicIfThenElse - ; - -logicAssignment - : identifierBecomes expr - | timeBecomes expr - | applicabilityBecomes expr - | identifierBecomes callPhrase - | (LPAREN dataVarList RPAREN ASSIGN | LET LPAREN dataVarList RPAREN BE) callPhrase - | identifierBecomes (newObjectPhrase | fuzzySetPhrase) - ; - -exprFuzzySet - : fuzzySetPhrase - | expr - ; +dataSwitchCases + : CASE exprFactor (dataStatement SC)* dataSwitchCases? # DataSwitchCase + | DEFAULT (dataStatement SC)* # DataSwitchDefault + ; + +dataIdentifierAssign + : READ (AS IDENTIFIER)? readPhrase # DataRead + | MLM (TERM (FROM INSTITUTION STRING)? | MLM_SELF) # DataMlm + | (INTERFACE | EVENT | MESSAGE | DESTINATION) mappingFactor # DataInterface + | (MESSAGE | DESTINATION) AS IDENTIFIER mappingFactor? # DataMessage + | ARGUMENT # DataArgument + | (OBJECT | LINGUISTIC VARIABLE) objectDefinition # DataObject + ; identifierBecomes - : identifierOrObjectRef ASSIGN - | LET identifierOrObjectRef BE - | NOW ASSIGN - ; + : identifierOrObjectRef ASSIGN + | LET identifierOrObjectRef BE + ; -logicSwitch - : SWITCH IDENTIFIER COLON logicSwitchCases ENDSWITCH AGGREGATE? - ; +timeBecomes + : TIME OF? identifierOrObjectRef ASSIGN + | LET TIME OF? identifierOrObjectRef BE + ; -logicSwitchCases - : (CASE exprFactor logicBlock logicSwitchCases)? - | DEFAULT logicBlock - ; +applicabilityBecomes + : APPLICABILITY OF? identifierOrObjectRef ASSIGN + | LET APPLICABILITY OF? identifierOrObjectRef BE + ; + +dataVarList + : identifierOrObjectRef (COMMA dataVarList)? + ; identifierOrObjectRef - : IDENTIFIER - | identifierOrObjectRef (LBRACK expr RBRACK | DOT identifierOrObjectRef) - ; + : IDENTIFIER # IdentifierRefIdentifier + | identifierOrObjectRef LBRACK expr RBRACK # IdentifierRefBrack + | identifierOrObjectRef DOT IDENTIFIER # IdentifierRefObject + ; -timeBecomes - : TIME OF? identifierOrObjectRef ASSIGN - | LET TIME OF? identifierOrObjectRef BE - ; +newObjectPhrase + : NEW IDENTIFIER (WITH (expr | LBRACK objectInitList RBRACK | expr WITH LBRACK objectInitList RBRACK))? + ; -applicabilityBecomes - : APPLICABILITY OF? identifierOrObjectRef ASSIGN - | LET APPLICABILITY OF? identifierOrObjectRef BE - ; +objectInitList + : objectInitElement (COMMA objectInitElement)* + ; + +objectInitElement + : (IDENTIFIER ASSIGN | LET IDENTIFIER BE) expr + ; + +fuzzySetPhrase + : FUZZY SET fuzzySetInitElement (COMMA fuzzySetInitElement)* # FuzzySet + | exprNegation FUZZIFIED BY exprNegation # FuzzifiedBy + ; + +fuzzySetInitElement + : LPAREN exprNegation COMMA exprNegation RPAREN + ; + +readPhrase + : (ofReadFuncOp OF?)? mappingFactor (WHERE exprOr)? # OfReadFuncOpReadWhere + | fromOfFuncOp OF? mappingFactor (WHERE exprOr)? # FromOfFuncOpReadWhere + | fromOfFuncOp exprFactor FROM mappingFactor (WHERE exprOr)? # FromOfFuncOpFromReadWhere + ; + +mappingFactor + : LBRACE DATA_MAPPING RBRACE + ; callPhrase - : CALL IDENTIFIER (WITH expr)? - ; + : CALL IDENTIFIER (WITH expr)? + ; + +fhirObject + : IDENTIFIER (LBRACK dataVarList RBRACK)? + ; + +fhirReadPhrase + : WHERE fhirAccessPhrase (AND fhirAccessPhrase)* + ; + +fhirAccessPhrase + : IT (DOT IDENTIFIER)+ fhirCompOp exprFactor # FhirCompOpAccess + | FIND exprFactor IN IT (DOT IDENTIFIER)+ # FhirFindInAccess + ; + +fhirCompOp + : simpleCompOp # FhirCompOpSimple + | NOT? EQUAL # FhirCompOpNot + | LESS THAN (OR EQUAL)? # FhirCompOpLess + | GREATER THAN (OR EQUAL)? # FhirCompOpGreater + | IS (IN | NOT) # FhirCompOpIs + ; + +objectDefinition + : LBRACK IDENTIFIER (COMMA IDENTIFIER)* RBRACK + ; + +evokeStatement + : simpleTrigger # EvokeSimple + | delayedEventTrigger # EvokeDelayedEvent + | constantTimeTrigger # EvokeConstantTime + | EVERY evokeDuration FOR evokeDuration STARTING startingDelay (UNTIL expr)? # EvokePeriodicEvent + | EVERY evokeDuration FOR evokeDuration STARTING constantTimeTrigger (UNTIL expr)? # EvokePeriodicConstantTime + ; + +simpleTrigger + : eventOr # SimpleEventOr + | ANY OF? LPAREN eventList RPAREN # SimpleEventList + ; + +delayedEventTrigger + : evokeTimeOr AFTER TIME OF? IDENTIFIER + ; + +constantTimeTrigger + : evokeTimeOr # ConstantTimeOr + | evokeDuration AFTER evokeTime # ConstantAfter + ; + +eventOr + : IDENTIFIER (OR IDENTIFIER)* + ; + +eventList + : IDENTIFIER (COMMA IDENTIFIER)* + ; + +evokeTimeOr + : evokeTimeExpr (OR evokeTimeExpr)* + ; + +evokeTimeExpr + : evokeTime # EvokeExprTime + | evokeDuration # EvokeExprDuration + ; + +evokeTime + : (ISO_DATE_TIME | ISO_DATE) # EvokeIso + | (TODAY | TOMORROW | WEEKDAYLITERAL) ATTIME TIME_OF_DAY # EvokeRelative + ; + +evokeDuration + : NUMBER durationOp + ; + +startingDelay + : delayedEventTrigger # StartingDelayed + | TIME OF? IDENTIFIER # StartingEvent + ; + +logicStatement + : (identifierBecomes | timeBecomes | applicabilityBecomes) expr # LogicIdentifierAssignSimple + | identifierBecomes (newObjectPhrase | callPhrase | fuzzySetPhrase) # LogicIdentifierAssignComplex + | (LPAREN dataVarList RPAREN ASSIGN | LET LPAREN dataVarList RPAREN BE) callPhrase # LogicDataVarList + | IF expr THEN (logicStatement SC)* logicElseIf AGGREGATE? # LogicIf + | FOR identifierOrObjectRef IN expr DO (logicStatement SC)* ENDDO # LogicFor + | WHILE expr DO (logicStatement SC)* ENDDO # LogicWhile + | SWITCH identifierOrObjectRef logicSwitchCases ENDSWITCH AGGREGATE? # LogicSwitch + | BREAKLOOP # LogicBreakLoop + | CONCLUDE expr # LogicConclude + ; + +logicElseIf + : ENDIF # LogicEndIf + | ELSE (logicStatement SC)* ENDIF # LogicElse + | ELSEIF expr THEN (logicStatement SC)* logicElseIf # LogicElseIfRecursive + ; + +logicSwitchCases + : CASE exprFactor (logicStatement SC)* logicSwitchCases? # LogicSwitchCase + | DEFAULT (logicStatement SC)* # LogicSwitchDefault + ; + +actionStatement + : (identifierBecomes | applicabilityBecomes) (expr | CONCLUDE) # ActionIdentifierAssign + | IF expr THEN (actionStatement SC)* actionElseIf AGGREGATE? # ActionIf + | FOR identifierOrObjectRef IN expr DO (actionStatement SC)* ENDDO # ActionFor + | WHILE expr DO (actionStatement SC)* ENDDO # ActionWhile + | SWITCH identifierOrObjectRef actionSwitchCases ENDSWITCH AGGREGATE? # ActionSwitch + | timeBecomes expr # ActionTimeAssign + | identifierBecomes newObjectPhrase # ActionIdentifierAssignObject + | callPhrase (DELAY expr)? # ActionCallPhrase + | WRITE expr (AT IDENTIFIER)? # ActionWrite + | RETURN expr # ActionReturn + | BREAKLOOP # ActionBreakLoop + ; + +actionElseIf + : ENDIF # ActionEndIf + | ELSE (actionStatement SC)* ENDIF # ActionElse + | ELSEIF expr THEN (actionStatement SC)* actionElseIf # ActionElseIfRecursive + ; + +actionSwitchCases + : CASE exprFactor (actionStatement SC)* actionSwitchCases? # ActionSwitchCase + | DEFAULT (actionStatement SC)* # ActionSwitchDefault + ; -// Expressions expr - : exprSort - | expr COMMA exprSort - | COMMA exprSort - ; + : COMMA? exprMerge # ListUnary + | expr COMMA exprMerge # ListBinary + ; -exprSort - : exprAddList (MERGE exprSort)? - | SORT sortOption exprSort (USING exprFunction)? - | exprAddList MERGE exprSort USING exprFunction - ; +exprMerge + : exprSort # ToExprSort + | exprMerge MERGE exprSort # MergeBinary + ; -sortOption - : DATAWC? - | TIME - | APPLICABILITY - ; +exprSort + : (SORT (DATA | TIME | APPLICABILITY)?)? exprAddList (USING exprFunction)? + ; exprAddList - : exprRemoveList - | ADD exprWhere TO exprWhere (AT exprWhere)? - ; + : ADD? exprRemoveList (TO exprRemoveList (AT exprRemoveList)?)? + ; exprRemoveList - : exprWhere - | REMOVE exprWhere FROM exprWhere - ; + : (REMOVE exprWhere FROM)? exprWhere + ; exprWhere - : exprRange (WHERE exprRange)? - ; - -exprRange - : exprOr (SEQTO exprOr)? - ; + : exprOr (WHERE exprOr)? + ; exprOr - : exprOr OR exprAnd - | exprAnd - ; + : exprAnd # ToAnd + | exprOr OR exprAnd # OrBinary + ; exprAnd - : exprAnd AND exprNot - | exprNot - ; + : exprRange # ToRange + | exprAnd AND exprRange # AndBinary + ; + +exprRange + : exprNot (SEQTO exprNot)? + ; exprNot - : NOT? exprComparison - ; + : NOT? exprComparison + ; exprComparison - : exprString - | exprFindString - | exprString singleCompOp exprString - | exprString IS? NOT? (mainCompOp | inCompOp) - | exprString OCCUR NOT? (temporalCompOp | rangeCompOp) - | exprString MATCHES PATTERN exprString - ; - -exprFindString - : FIND exprString IN? STRINGOP exprString stringSearchStart - ; + : exprString (simpleCompOp exprString)? # SimpleComparisonBinary + | FIND exprString IN? STRINGOP exprComparison (STARTING AT exprString)? # FindInStringTernary + | exprString IS NOT? mainCompOp # ComparisonIsMainCompOp + | exprString NOT? IN exprString # InBinary + | exprString OCCUR NOT? (binaryCompOpOccur exprString | ternaryCompOp | AT exprString) # ComparisonOccur + | exprString MATCHES PATTERN exprString # MatchesPatternBinary + ; exprString - : exprPlus - | exprString ('||' | FORMATTED WITH) exprPlus - | TRIM trimOption exprString - | caseOption exprString - | SUBSTRING exprPlus CHARACTERS stringSearchStart FROM exprString - ; - -trimOption - : LEFT? - | RIGHT - ; - -caseOption - : UPPERCASE - | LOWERCASE - ; - -stringSearchStart - : (STARTING AT exprPlus)? - ; + : exprPlus # ToExprPlus + | exprString (DOR | FORMATTED WITH) exprPlus # DorFormattedWithBinary + | TRIM (LEFT | RIGHT)? exprString # TrimUnary + | (UPPERCASE | LOWERCASE) exprString # StringCaseUnary + | SUBSTRING exprPlus CHARACTERS (STARTING AT exprPlus)? FROM exprString # SubstringCharactersTernary + ; exprPlus - : exprTimes - | exprPlus (PLUS | MINUS) exprTimes - | (PLUS | MINUS) exprTimes - ; + : exprMul ((PLUS | MINUS) exprMul)* + ; -exprTimes - : exprPower - | exprTimes (MUL | DIV) exprPower - ; +exprMul + : exprPower ((MUL | DIV) exprPower)* + ; exprPower - : exprAtTime - | exprFunction POWER exprFunction - ; + : exprAtTime (POWER exprAtTime)? + ; exprAtTime - : exprBefore (ATTIME exprAtTime)? - ; + : exprBefore (ATTIME exprAtTime)? + ; exprBefore - : exprAgo - | exprDuration (BEFORE | AFTER | FROM) exprAgo - ; + : exprAgo # ToExprAgo + | exprAgo (BEFORE | AFTER | FROM) exprAgo # BeforeAfterFrom + ; exprAgo - : exprDuration AGO? - ; - -exprDuration - : exprFunction durationOp? - ; + : exprFunction AGO? + ; exprFunction - : exprFactor - | ofFuncOp OF? exprFunction - | fromOfFuncOp OF? exprFunction - | fromOfFuncOp exprFactor FROM exprFunction - | REPLACE timePart OF? exprFunction WITH exprFactor - | fromOfFuncOp OF? exprFunction USING exprFunction - | fromOfFuncOp exprFactor FROM exprFunction USING exprFunction - | fromFuncOp exprFactor FROM exprFunction - | indexFromOfFuncOp OF? exprFunction - | indexFromOfFuncOp exprFactor FROM exprFunction - | atLeastMostOp exprFactor (ISTRUE | ARETRUE)? FROM exprFunction - | (INDEX OF | indexFromFuncOp) exprFactor FROM exprFunction - | exprFactor AS asFuncOp - | exprAttributeFrom - | exprSubListFrom - ; - -exprAttributeFrom - : ATTRIBUTE exprFactor FROM exprFactor - ; - -exprSubListFrom - : SUBLIST exprFactor ELEMENTS (STARTING AT exprFactor)? FROM exprFactor - ; + : exprNegation (AS (NUMBEROP | TIME | STRINGOP | TRUTHVALUE))? # AsUnary + | (ofReadFuncOp | ofNoReadFuncOp) OF? exprFunction # FuncOpsUnary + | fromOfFuncOp OF? exprFunction (USING exprFunction)? # FromOfFuncOpUnary + | REPLACE timePart OF? exprNegation WITH exprFunction # ReplaceWithBinary + | fromOfFuncOp exprNegation FROM exprFunction (USING exprFunction)? # FromOfFuncOpBinary + | NEAREST exprNegation FROM exprFunction # NearestFromBinary + | INDEX indexFromOfFuncOp OF? exprFunction # IndexUnary + | INDEX (MINIMUM | MAXIMUM) OF? exprNegation FROM exprFunction # IndexFromMinMax + | AT (LEAST | MOST) exprNegation OF? ((ISTRUE | ARETRUE)? FROM)? exprFunction # AtLeastMostBinary + | INDEX OF? exprNegation FROM exprFunction # IndexFromBinary + | INDEX NEAREST exprNegation FROM exprFunction # IndexNearestBinary + | ATTRIBUTE exprNegation FROM exprFunction # AttributeFromBinary + | SUBLIST exprNegation ELEMENTS (STARTING AT exprNegation)? FROM exprFunction # SublistTernary + ; + +exprNegation + : (PLUS | MINUS)? exprDuration + ; + +exprDuration + : exprFactor durationOp? + ; exprFactor - : exprFactorAtom (LBRACK expr RBRACK)? - | exprFactor DOT IDENTIFIER - ; - -exprFactorAtom - : IDENTIFIER - | NUMBER - | string - | timeValue - | booleanValue - | WEEKDAYLITERAL - | TODAY - | TOMORROW - | NULL - | CONCLUDE - | IT - | LPAREN (expr | exprFuzzySet)? RPAREN - ; - -singleCompOp - : EQ - | LT - | GT - | LE - | GE - | NE - ; + : exprAtom # ToAtom + | exprFactor LBRACK expr RBRACK # FactorBrack + | exprFactor DOT IDENTIFIER # FactorDot + ; + +exprAtom + : (IDENTIFIER | NUMBER | NULL | IT) # AtomMisc + | (STRING | (LOCALIZED TERM (BY exprAtom)?)) # AtomString + | (NOW | ISO_DATE_TIME | ISO_DATE | EVENTTIME | TRIGGERTIME | CURRENTTIME | TIME_OF_DAY | TODAY | TOMORROW | WEEKDAYLITERAL) # AtomTime + | ((TRUTHVALUE? (TRUE | FALSE)) | TRUTHVALUE NUMBER) # AtomBoolean + | LPAREN (expr | fuzzySetPhrase)? RPAREN # AtomRecursive + ; + +simpleCompOp + : (EQ | LT | GT | LE | GE | NE) + ; mainCompOp - : temporalCompOp - | rangeCompOp - | unaryCompOp - | binaryCompOp exprString - ; - -rangeCompOp - : WITHIN exprString TO exprString - ; - -temporalCompOp - : WITHIN exprString (PRECEDING | FOLLOWING | SURROUNDING) exprString - | WITHIN (PAST | SAME DAY AS) exprString - | (BEFORE | AFTER | EQUAL) exprString - | AT exprString - ; + : unaryCompOp # ToUnaryCompOp + | binaryCompOp exprString # ToBinaryCompOp + | binaryCompOpOccur exprString # ToBinaryCompOpOccur + | ternaryCompOp # ToTernaryCompOp + ; unaryCompOp - : PRESENT - | NULL - | BOOLEAN - | TRUTHVALUE - | CRISP - | FUZZY - | NUMBEROP - | TIME - | DURATION - | STRINGOP - | LIST - | OBJECT - | LINGUISTIC VARIABLE - | IDENTIFIER - | TIME OF DAY - ; + : (PRESENT | NULL | BOOLEAN | TRUTHVALUE | NUMBEROP | STRINGOP | TIME | DURATION | LIST | OBJECT | IDENTIFIER | FUZZY | CRISP) + | TIME OF DAY + | LINGUISTIC VARIABLE + ; binaryCompOp - : (LESS | GREATER) THAN (OR EQUAL)? - | IN - ; + : LESS THAN (OR EQUAL)? + | GREATER THAN (OR EQUAL)? + | IN + ; -ofFuncOp - : ofReadFuncOp - | ofNoreadFuncOp - ; +binaryCompOpOccur + : (EQUAL | BEFORE | AFTER) + | WITHIN (PAST | SAME DAY AS) + ; -inCompOp - : IN exprString - ; +ternaryCompOp + : WITHIN exprString (TO | PRECEDING | FOLLOWING | SURROUNDING) exprString + ; ofReadFuncOp - : AVERAGE - | COUNT - | EXIST - | SUM - | MEDIAN - ; - -ofNoreadFuncOp - : ANY ISTRUE? - | ALL ARETRUE? - | NO ISTRUE? - | SLOPE - | STDDEV - | VARIANCE - | INCREASE - | PERCENT? (INCREASE | DECREASE) - | INTERVAL - | TIME (OF DAY)? - | DAY OF WEEK - | ARCCOS - | ARCSIN - | ARCTAN - | COSINE - | SINE - | TANGENT - | EXP - | FLOOR - | INT - | ROUND - | CEILING - | TRUNCATE - | LOG - | LOG10 - | ABS - | SQRT - | EXTRACT (YEAR | MONTH | DAY | HOUR | MINUTE | SECOND | TIME OF DAY) - | STRINGOP - | EXTRACT CHARACTERS - | REVERSE - | LENGTH - | CLONE - | EXTRACT ATTRIBUTE NAMES - | APPLICABILITY - | DEFUZZIFIED - ; - -fromFuncOp - : NEAREST - ; - -indexFromFuncOp - : INDEX NEAREST - ; + : (AVERAGE | COUNT | EXIST | SUM | MEDIAN) + ; + +ofNoReadFuncOp + : (SLOPE | STDDEV | VARIANCE | INTERVAL | ARCCOS | ARCSIN | ARCTAN | COSINE | SINE | TANGENT | EXP | FLOOR | INT | ROUND | CEILING | TRUNCATE | LOG | LOG10 | ABS | SQRT | STRINGOP | REVERSE | LENGTH | CLONE | APPLICABILITY | DEFUZZIFIED) + | ANY ISTRUE? + | ALL ARETRUE? + | NO ISTRUE? + | PERCENT? (INCREASE | DECREASE) + | TIME (OF DAY)? + | DAY OF WEEK + | EXTRACT (YEAR | MONTH | DAY | HOUR | MINUTE | SECOND | CHARACTERS | ATTRIBUTE NAMES) + ; fromOfFuncOp - : MINIMUM - | MAXIMUM - | LAST - | FIRST - | EARLIEST - | LATEST - ; + : (MINIMUM | MAXIMUM | LAST | FIRST | EARLIEST | LATEST) + ; indexFromOfFuncOp - : INDEX (MINIMUM | MAXIMUM | EARLIEST | LATEST) - ; - -asFuncOp - : NUMBEROP - | TIME - | STRINGOP - | TRUTHVALUE - ; - -atLeastMostOp - : AT (LEAST | MOST) - ; + : (MINIMUM | MAXIMUM | EARLIEST | LATEST) + ; durationOp - : YEAR - | MONTH - | WEEK - | DAY - | HOUR - | MINUTE - | SECOND - ; + : (YEAR | MONTH | WEEK | DAY | HOUR | MINUTE | SECOND) + ; timePart - : YEAR - | MONTH - | DAY - | HOUR - | MINUTE - | SECOND - ; - -// Factors -string - : STRING - | LOCALIZED TERM localizeOption - ; - -localizeOption - : (BY STRING)? - | BY IDENTIFIER - ; - -booleanValue - : TRUTHVALUE? (TRUE | FALSE) - | TRUTHVALUE NUMBER - ; - -timeValue - : NOW - | ISO_DATE_TIME - | ISO_DATE - | EVENTTIME - | TRIGGERTIME - | CURRENTTIME - | TIMEOFDAY - ; - -// Data block -dataBlock - : dataBlock SC dataStatement - | dataStatement - ; - -dataStatement - : dataAssignment? - | IF dataIfThenElse - | FOR IDENTIFIER IN expr DO dataBlock SC ENDDO - | WHILE expr DO dataBlock SC ENDDO - | dataSwitch - | BREAKLOOP - | INCLUDE IDENTIFIER - ; - -dataIfThenElse - : expr THEN dataBlock SC dataElseIf - ; - -dataElseIf - : ENDIF AGGREGATE? - | ELSE dataBlock SC ENDIF AGGREGATE? - | ELSEIF dataIfThenElse - ; - -dataSwitch - : SWITCH IDENTIFIER COLON dataSwitchCases ENDSWITCH AGGREGATE? - ; - -dataSwitchCases - : (CASE exprFactor dataBlock dataSwitchCases)? - | DEFAULT dataBlock - ; - -dataAssignment - : identifierBecomes dataAssignPhrase - | timeBecomes expr - | applicabilityBecomes expr - | (LPAREN dataVarList RPAREN ASSIGN | LET LPAREN dataVarList RPAREN BE) ( - READ (AS IDENTIFIER)? readPhrase - | ARGUMENT - ) - ; - -dataVarList - : identifierOrObjectRef (COMMA dataVarList)? - ; - -dataAssignPhrase - : READ (AS IDENTIFIER)? readPhrase - | MLM (TERM (FROM INSTITUTIONWC string)? | MLM_SELF) - | (INTERFACE | EVENT | MESSAGE) mappingFactor - | MESSAGE AS IDENTIFIER mappingFactor? - | DESTINATION (mappingFactor AS IDENTIFIER mappingFactor?) - | ARGUMENT - | OBJECT objectDefinition - | LINGUISTIC VARIABLE objectDefinition - | callPhrase - | newObjectPhrase - | fuzzySetPhrase - | expr - ; - -fuzzySetPhrase - : FUZZY SET fuzzySetInitList - | exprDuration FUZZIFIED BY exprDuration - | exprFactor FUZZIFIED BY exprFactor - ; - -fuzzySetInitList - : fuzzySetInitElement - | fuzzySetInitList COMMA fuzzySetInitElement - ; - -fuzzySetInitElement - : LPAREN fuzzySetInitFactor COMMA exprFactor RPAREN - ; - -fuzzySetInitFactor - : exprFactor - | NUMBER durationOp - ; - -readPhrase - : readWhere - | ofReadFuncOp OF? readWhere - | fromOfFuncOp OF? readWhere - | fromOfFuncOp exprFactor FROM readWhere - ; - -readWhere - : mappingFactor (WHERE IT OCCUR NOT? (temporalCompOp | rangeCompOp))? - | LPAREN readWhere RPAREN - ; - -mappingFactor - : LBRACE DATA_MAPPING RBRACE - ; - -objectDefinition - : LBRACK objectAttributeList RBRACK - ; - -objectAttributeList - : IDENTIFIER (COMMA objectAttributeList)? - ; - -newObjectPhrase - : NEW IDENTIFIER (WITH (expr | (expr WITH)? LBRACK objectInitList RBRACK))? - ; - -objectInitList - : objectInitElement - | objectInitList COMMA objectInitElement - ; - -objectInitElement - : IDENTIFIER ASSIGN expr - ; - -// Evoke block -evokeBlock - : evokeStatement - | evokeBlock SC evokeStatement - ; - -evokeStatement - : eventOr? - | evokeTime - | delayedEvoke - | qualifiedEvokeCycle - | CALL - ; - -eventList - : eventOr - | eventList COMMA eventOr - ; - -eventOr - : eventOr OR eventAny - | eventAny - ; - -eventAny - : ANY OF? (LPAREN eventList RPAREN | IDENTIFIER) - | eventFactor - ; - -eventFactor - : LPAREN eventOr RPAREN - | IDENTIFIER - ; - -delayedEvoke - : evokeTimeExprOr (AFTER eventTime)? - | evokeDuration AFTER evokeTimeOr - ; - -eventTime - : TIME OF? eventAny - ; - -evokeTimeOr - : evokeTime - | evokeTime OR evokeTimeOr - ; - -evokeTimeExprOr - : evokeTimeExpr - | evokeTimeExpr OR evokeTimeExprOr - ; - -evokeTimeExpr - : evokeDuration - | evokeTime - ; - -evokeTime - : ISO_DATE_TIME - | ISO_DATE - | relativeEvokeTimeExpr - ; - -evokeDuration - : NUMBER durationOp - ; - -relativeEvokeTimeExpr - : (TODAY | TOMORROW | WEEKDAYLITERAL) ATTIME TIMEOFDAY - ; - -qualifiedEvokeCycle - : simpleEvokeCycle (UNTIL expr)? - ; - -simpleEvokeCycle - : EVERY evokeDuration FOR evokeDuration STARTING startingDelay - ; - -startingDelay - : eventTime - | delayedEvoke - ; - -// Action block -actionBlock - : actionStatement - | actionBlock SC actionStatement - ; - -actionStatement - : (IF actionIfThenElse)? - | FOR IDENTIFIER IN expr DO actionBlock SC ENDDO - | WHILE expr DO actionBlock SC ENDDO - | actionSwitch - | BREAKLOOP - | callPhrase (DELAY expr)? - | WRITE expr (AT IDENTIFIER)? - | RETURN expr - | identifierBecomes expr - | timeBecomes expr - | applicabilityBecomes expr - | identifierBecomes newObjectPhrase - ; - -actionIfThenElse - : expr THEN actionBlock SC actionElseIf - ; - -actionElseIf - : ENDIF AGGREGATE? - | ELSE actionBlock SC ENDIF AGGREGATE? - | ELSEIF actionIfThenElse - ; - -actionSwitch - : SWITCH IDENTIFIER COLON actionSwitchCases ENDSWITCH AGGREGATE? - ; - -actionSwitchCases - : (CASE exprFactor actionBlock actionSwitchCases)? - | DEFAULT actionBlock - ; \ No newline at end of file + : (YEAR | MONTH | DAY | HOUR | MINUTE | SECOND) + ; \ No newline at end of file diff --git a/arden/README.md b/arden/README.md index 045e3e2616..275a3ff100 100644 --- a/arden/README.md +++ b/arden/README.md @@ -2,4 +2,4 @@ An ANTLR4 grammar for [Arden Syntax](http://www.hl7.org/special/Committees/arden/index.cfm). -The examples are from the arden syntax document v2.10 found [here](http://www.hl7.org/implement/standards/product_brief.cfm?product_id=372). \ No newline at end of file +The examples are from the arden syntax document v3.0 found [here](http://www.hl7.org/implement/standards/product_brief.cfm?product_id=372). \ No newline at end of file diff --git a/arden/desc.xml b/arden/desc.xml index 1b8ebc91a1..9083803440 100644 --- a/arden/desc.xml +++ b/arden/desc.xml @@ -1,5 +1,4 @@ - ^4.10 - CSharp;Cpp;Dart;Java + CSharp;Cpp;Dart;Java \ No newline at end of file diff --git a/arden/examples/Contraindication Alert.mlm b/arden/examples/Contraindication Alert.mlm new file mode 100644 index 0000000000..5338519bc4 --- /dev/null +++ b/arden/examples/Contraindication Alert.mlm @@ -0,0 +1,45 @@ +maintenance: +title: Check for penicillin allergy;; +mlmname: pen_allergy;; +arden: version 3;; +version: 1.00;; +institution: Columbia-Presbyterian Medical Center;; +author: George Hripcsak, M.D.;; +specialist: ;; +date: 1991-03-18;; +validation: testing;; +library: +purpose: +When a penicillin is prescribed, check for an allergy. (This MLM +demonstrates checking for contraindications.);; +explanation: +This MLM is evoked when a penicillin medication is ordered. An +alert is generated because the patient has an allergy to penicillin +recorded.;; +keywords: penicillin; allergy;; +citations: ;; +knowledge: +type: data-driven;; +data: /* an order for a penicillin evokes this MLM */ +penicillin_order := event {medication_order where +class = penicillin}; +/* find allergies */ +penicillin_allergy := read last {allergy where +agent_class = penicillin}; +;; +evoke: penicillin_order; +;; +logic: if exist(penicillin_allergy)then +conclude true; +endif; +;; +action: +write "Caution, the patient has the following allergy to penicillin +documented:" +|| penicillin_allergy; +;; +urgency: 50;; +resources: +default: en;; +language: en;; +end: \ No newline at end of file diff --git a/arden/examples/First.mlm b/arden/examples/Data Interpretation.mlm similarity index 83% rename from arden/examples/First.mlm rename to arden/examples/Data Interpretation.mlm index a45b5e84eb..87fb0d8cac 100644 --- a/arden/examples/First.mlm +++ b/arden/examples/Data Interpretation.mlm @@ -19,22 +19,25 @@ The fractional excretion of sodium is calculated from the urine sodium and creatinine and the most recent serum sodium and creatinine (where they occurred within the past 24 hours). A value less than 1.0 % is considered low.;; -keywords: fractional excretion; serum sodium; azotemia;; +keywords: fractional excretion; serum sodium; azotemia;; citations: -1. refute "Steiner RW. Interpreting the fractional excretion of sodium. -Am J Med 1984;77:699-702.";; +1. Steiner RW. Interpreting the fractional excretion of sodium. +Am J Med 1984;77:699-702.;; knowledge: type: data-driven;; -data: let (urine_na, urine_creat) be read last -({urine electrolytes where evoking} -where they occurred within the past 24 hours); +data: +let (urine_na, urine_creat) be read last +{urine electrolytes where evoking} +where they occurred within the past 24 hours; let (serum_na, serum_creat) be read last -({serum electrolytes where they are not null} -where they occurred within the past 24 hours); +{serum electrolytes where they are not null} +where they occurred within the past 24 hours; let urine_electrolyte_storage be event {storage of urine electrolytes}; ;; -evoke: urine_electrolyte_storage;; +evoke: +urine_electrolyte_storage; +;; logic: /* calculate fractional excretion of sodium */ let fractional_na be 100 * (urine_na / urine_creat) / (serum_na / serum_creat); @@ -69,4 +72,7 @@ write "The calculated fractional excretion of sodium is " || "volume depletion."; endif; ;; -end: \ No newline at end of file +resources: +default: en;; +language: en;; +end: diff --git a/arden/examples/Fourth.mlm b/arden/examples/Fourth.mlm deleted file mode 100644 index f99df212e1..0000000000 --- a/arden/examples/Fourth.mlm +++ /dev/null @@ -1,237 +0,0 @@ -maintenance: -title: Cardiology MLM from CARE, p. 85;; -mlmname: care_cardiology_mlm;; -arden: Version 3;; -version: 1.00;; -institution: Regenstrief Institute;; -author: Clement J. McDonald, M.D.; George Hripcsak, M.D.;; -specialist: ;; -date: 1991-05-28;; -validation: testing;; -library: -purpose: -Recommend higher beta-blocker dosage if it is currently low and the -patient is having excessive angina or premature ventricular -beats.;; -explanation: -If the patient is not bradycardic and is taking less than 360 mg of -propanolol or less than 200 mg of metoprolol, then if the patient -is having more than 4 episodes of angina per month or more than 5 -premature ventricular beats per minute, recommend a higher dose.;; -keywords: -beta-blocker, angina; premature ventricular beats; bradycardia;; -citations: -1. support "McDonald CJ. Action-oriented decisions in ambulatory medicine. -Chicago: Year Book Medical Publishers, 1981, p. 85."; -2. refute "Prichard NC, Gillam PM. Assessment of propranolol in angina -pectoris: clinical dose response curve and effect on -electrocardiogram at rest and on exercise. Br Heart J, -33:473-480 (1971)." ; -3. support "Jackson G, Atkinson L, Oram S. Reassessment of failed beta- -blocker treatment in angina pectoris by peak exercise heart rate -measurements. Br Med J, 3:616-619 (1975)." -;; -knowledge: -type: data-driven;; -data: let last_clinic_visit be read last {CLINIC_VISIT}; -let (beta_meds, beta_doses, beta_statuses) be read -{MEDICATION, DOSE, STATUS -where the beta_statuses are ‘current’ -and beta_meds are a kind of ‘beta_blocker’}; -let low_dose_beta_use be false; -/* if patient is on one beta blocker, check if it is low dose */ -if the count ofbeta_meds = 1 then -if (last beta_meds = "propanolol" -and -last beta_doses < 360) -or (the last beta_meds = "metoprolol" -and -the last beta_doses <= 200) then -let low_dose_beta_use be true; -endif; -endif; -let cutoff_time be the maximum of -((1 month ago),(time of last_clinic_visit), -(time of last beta_meds)); -/* a system-specific query to angina frequency, PVC frequency, */ -/* and pulse rate would replace capitalized terms */ -let angina_frequency be read last ({ANGINA_FREQUENCY} -where it occurred after cutoff_time); -let premature_beat_frequency be read last -({PREMATURE_BEAT_FREQUENCY} -where it occurred after cutoff_time); -let last_pulse_rate be read last {PULSE_RATE}; -;; -evoke: /* this MLM is called directly */;; -logic: if last_pulse_rate is greater than 60 and -low_dose_beta_use then -if angina_frequency is greater than 4 then -let msg be -"Increased dose of beta blockers may be " || -"needed to control angina."; -conclude true; -elseif premature_beat_frequency is greater than 5 then -let msg be -"Increased dose of beta blockers may " || -"be needed to control PVC's."; -conclude true; -endif; -endif; -conclude false; -;; -action: write msg;; -end: - -maintenance: -title: Allergy_test_with_while_loop;; -filename: test_for_allergies_while_loop;; -version: 0.00;; -institution: ;; -author: ;; -specialist: ;; -date: 1997-11-06;; -validation: testing;; -library: -purpose: -Illustrates the use of a WHILE-LOOP that processes an entire list -;; -explanation: -;; -keywords: -;; -knowledge: -type: data-driven;; -data: /* Receives four arguments from the calling MLM: */ -(med_orders, -med_allergens, -patient_allergies, -patient_reactions) := ARGUMENT; -;; -evoke: ;; -logic: /* Initializes variables */ -a_list:= (); -m_list:= (); -r_list:= (); -num:= 1; -/* Checks each allergen in the medications to determine */ -/* if the patient is allergic to it */ -while num <= (count med_allergen) do -allergen:= last(first num from med_allergens); -allergy_found:= (patient_allergies = allergen); -reaction:= patient_reactions where allergy_found; -medication:= med_orders where (med_allergens = allergen); -/* Adds the allergen, medication, and reaction to */ -/* variables that will be returned to the calling MLM */ -If any allergy_found then -a_list:= a_list, allergen; -m_list:= m_list, medication; -r_list:= r_list, reaction; -endif; -/* Increments the counter that is used to stop the while-loop */ -num:= num + 1; -enddo; -/* Concludes true if the patient is allergic to one of */ -/* the medications */ -If exist m_list then -conclude true; -endif; -;; -action: /* Returns three lists to the calling MLM */ -return m_list, a_list, r_list; -;; -end: - -maintenance: -title: Increased body temperature - crisp;; -mlmname: increased_body_temperature_crisp;; -arden: version 3;; -version: ;; -institution: ;; -author: ;; -specialist: ;; -date: 2011-07-06;; -validation: testing;; -library: -purpose: detects an increased body temperatur over a day - absolute criterion;; -explanation: Check if maximum of body temperature is increased with -crisp logic. -reads parameter: "TempMax" (in degree Celsius). -;; -keywords: body temperature, temperature, data to symbol conversion;; -citations: ;; -knowledge: -type: data_driven;; -data: ///////////////////////////////////////// -readParam := interface {read param}; // read single parameter -;; -evoke: ;; -logic: /////////////////////////////////////// -// read precondition from host -paramTempMax := call readParam with "TempMax"; -// calculation of result -if paramTempMax is present then -if paramTempMax >= 38 then -tempratureIncreased := 1; -time tempratureIncreased := time paramTempMax; -else -tempratureIncreased := 0; -time tempratureIncreased := time paramTempMax; -endif; -endif; -conclude true; -;; -action: /////////////////////////////////////// -write tempratureIncreased; -;; -end: - -maintenance: -title: Increased body temperature - fuzzy simulation;; -mlmname: increased_body_temperature_fuzzy_simulation;; -arden: version 3;; -version: ;; -institution: ;; -author: ;; -specialist: ;; -date: 2011-07-06;; -validation: testing;; -library: -purpose: detects an increased body temperatur over a day - absolute criterion;; -explanation: Check if maximum of body temperature is increased with -explicit coded fuzzy logic. -reads parameter: "TempMax" (in degree Celsius). -;; -keywords: body temperature, temperature, data to symbol conversion;; -citations: ;; -knowledge: -type: data_driven;; -data: ///////////////////////////////////////// -// interface -readParam := interface {read param}; // read single parameter -;; -evoke: ;; -logic: /////////////////////////////////////// -// read precondition from host -paramTempMax := call readParam with "TempMax"; -// calculation of result -if paramTempMax is present then -if paramTempMax >= 38 then -tempratureIncreased := 1; -time tempratureIncreased := time paramTempMax; -elseif paramTempMax > 37.5 then -tempratureIncreased := (paramTempMax - 37.5) / 0.5; -time tempratureIncreased := time paramTempMax; -else -tempratureIncreased := 0; -time tempratureIncreased := time paramTempMax; -endif; -endif; -conclude true; -;; -action: /////////////////////////////////////// -write tempratureIncreased; -;; -resources: -default: en;; -language: en;; -end: \ No newline at end of file diff --git a/arden/examples/MLM Fever Calculation - Crisp.mlm b/arden/examples/MLM Fever Calculation - Crisp.mlm new file mode 100644 index 0000000000..b4d52e424c --- /dev/null +++ b/arden/examples/MLM Fever Calculation - Crisp.mlm @@ -0,0 +1,46 @@ +maintenance: +title: Increased body temperature - crisp;; +mlmname: increased_body_temperature_crisp;; +arden: version 3;; +version: ;; +institution: ;; +author: ;; +specialist: ;; +date: 2011-07-06;; +validation: testing;; +library: +purpose: detects an increased body temperatur over a day - absolute criterion;; +explanation: Check if maximum of body temperature is increased with +crisp logic. +reads parameter: "TempMax" (in degree Celsius). +;; +keywords: body temperature, temperature, data to symbol conversion;; +citations: ;; +knowledge: +type: data_driven;; +data: ///////////////////////////////////////// +readParam := interface {read param}; // read single parameter +;; +evoke: ;; +logic: /////////////////////////////////////// +// read precondition from host +paramTempMax := call readParam with "TempMax"; +// calculation of result +if paramTempMax is present then +if paramTempMax >= 38 then +tempratureIncreased := 1; +time tempratureIncreased := time paramTempMax; +else +tempratureIncreased := 0; +time tempratureIncreased := time paramTempMax; +endif; +endif; +conclude true; +;; +action: /////////////////////////////////////// +write tempratureIncreased; +;; +resources: +default: en;; +language: en;; +end: \ No newline at end of file diff --git a/arden/examples/MLM Fever Calculation - Fuzzy Logic.mlm b/arden/examples/MLM Fever Calculation - Fuzzy Logic.mlm new file mode 100644 index 0000000000..7f9af1d51e --- /dev/null +++ b/arden/examples/MLM Fever Calculation - Fuzzy Logic.mlm @@ -0,0 +1,44 @@ +maintenance: +title: Increased body temperature - fuzzy;; +mlmname: increased_body_temperature_fuzzy;; +arden: version 3;; +version: ;; +institution: ;; +author: ;; +specialist: ;; +date: 2011-07-06;; +validation: testing;; +library: +purpose: detects an increased body temperatur over a day - absolute criterion;; +explanation: Check if maximum of body temperature is increased with +fuzzy logic. +reads parameter: "TempMax" (in degree Celsius). +;; +keywords: body temperature, temperature, data to symbol conversion;; +citations: ;; +knowledge: +type: data_driven;; +data: ///////////////////////////////////////// +// interface +readParam := interface {read param}; // read single parameter +;; +evoke: ;; +logic: /////////////////////////////////////// +// read precondition from host +paramTempMax := call readParam with "TempMax"; +// calculation of result +if paramTempMax is present then +// <= 37.5 °C: 0; >= 38 °C: 1; inbetween: linear +tempErh := fuzzy set (37.5, truth value 0), (38, truth value 1); +tempratureIncreased := paramTempMax is in tempErh; +time tempratureIncreased := time paramTempMax; +endif; +conclude true; +;; +action: /////////////////////////////////////// +write tempratureIncreased; +;; +resources: +default: en;; +language: en;; +end: \ No newline at end of file diff --git a/arden/examples/MLM Fever Calculation - Fuzzy Simulation.mlm b/arden/examples/MLM Fever Calculation - Fuzzy Simulation.mlm new file mode 100644 index 0000000000..05e4d6afb0 --- /dev/null +++ b/arden/examples/MLM Fever Calculation - Fuzzy Simulation.mlm @@ -0,0 +1,50 @@ +maintenance: +title: Increased body temperature - fuzzy simulation;; +mlmname: increased_body_temperature_fuzzy_simulation;; +arden: version 3;; +version: ;; +institution: ;; +author: ;; +specialist: ;; +date: 2011-07-06;; +validation: testing;; +library: +purpose: detects an increased body temperatur over a day - absolute criterion;; +explanation: Check if maximum of body temperature is increased with +explicit coded fuzzy logic. +reads parameter: "TempMax" (in degree Celsius). +;; +keywords: body temperature, temperature, data to symbol conversion;; +citations: ;; +knowledge: +type: data_driven;; +data: ///////////////////////////////////////// +// interface +readParam := interface {read param}; // read single parameter +;; +evoke: ;; +logic: /////////////////////////////////////// +// read precondition from host +paramTempMax := call readParam with "TempMax"; +// calculation of result +if paramTempMax is present then +if paramTempMax >= 38 then +tempratureIncreased := 1; +time tempratureIncreased := time paramTempMax; +elseif paramTempMax > 37.5 then +tempratureIncreased := (paramTempMax - 37.5) / 0.5; +time tempratureIncreased := time paramTempMax; +else +tempratureIncreased := 0; +time tempratureIncreased := time paramTempMax; +endif; +endif; +conclude true; +;; +action: /////////////////////////////////////// +write tempratureIncreased; +;; +resources: +default: en;; +language: en;; +end: \ No newline at end of file diff --git a/arden/examples/MLM Translated from CARE.mlm b/arden/examples/MLM Translated from CARE.mlm new file mode 100644 index 0000000000..47a4dfe0ac --- /dev/null +++ b/arden/examples/MLM Translated from CARE.mlm @@ -0,0 +1,88 @@ +maintenance: +title: Cardiology MLM from CARE, p. 85;; +mlmname: care_cardiology_mlm;; +arden: Version 3;; +version: 1.00;; +institution: Regenstrief Institute;; +author: Clement J. McDonald, M.D.; George Hripcsak, M.D.;; +specialist: ;; +date: 1991-05-28;; +validation: testing;; +library: +purpose: +Recommend higher beta-blocker dosage if it is currently low and the +patient is having excessive angina or premature ventricular +beats.;; +explanation: +If the patient is not bradycardic and is taking less than 360 mg of +propanolol or less than 200 mg of metoprolol, then if the patient +is having more than 4 episodes of angina per month or more than 5 +premature ventricular beats per minute, recommend a higher dose.;; +keywords: +beta-blocker, angina; premature ventricular beats; bradycardia;; +citations: +1. McDonald CJ. Action-oriented decisions in ambulatory medicine. +Chicago: Year Book Medical Publishers, 1981, p. 85. +2. Prichard NC, Gillam PM. Assessment of propranolol in angina +pectoris: clinical dose response curve and effect on +electrocardiogram at rest and on exercise. Br Heart J, +33:473-480 (1971). +3. Jackson G, Atkinson L, Oram S. Reassessment of failed beta- +blocker treatment in angina pectoris by peak exercise heart rate +measurements. Br Med J, 3:616-619 (1975). +;; +knowledge: +type: data-driven;; +data: let last_clinic_visit be read last {CLINIC_VISIT}; +let (beta_meds, beta_doses, beta_statuses) be read +{MEDICATION, DOSE, STATUS +where the beta_statuses are ‘current’ +and beta_meds are a kind of ‘beta_blocker’}; +let low_dose_beta_use be false; +/* if patient is on one beta blocker, check if it is low dose */ +if the count ofbeta_meds = 1 then +if (last beta_meds = "propanolol" +and +last beta_doses < 360) +or (the last beta_meds = "metoprolol" +and +the last beta_doses <= 200) then +let low_dose_beta_use be true; +endif; +endif; +let cutoff_time be the maximum of +((1 month ago),(time of last_clinic_visit), +(time of last beta_meds)); +/* a system-specific query to angina frequency, PVC frequency, */ +/* and pulse rate would replace capitalized terms */ +let angina_frequency be read last {ANGINA_FREQUENCY} +where it occurred after cutoff_time; +let premature_beat_frequency be read last +{PREMATURE_BEAT_FREQUENCY} +where it occurred after cutoff_time; +let last_pulse_rate be read last {PULSE_RATE}; +;; +evoke: /* this MLM is called directly */;; +logic: if last_pulse_rate is greater than 60 and +low_dose_beta_use then +if angina_frequency is greater than 4 then +let msg be +"Increased dose of beta blockers may be " || +"needed to control angina."; +conclude true; +elseif premature_beat_frequency is greater than 5 then +let msg be +"Increased dose of beta blockers may " || +"be needed to control PVC's."; +conclude true; +endif; +endif; +conclude false; +;; +action: +write msg; +;; +resources: +default: en;; +language: en;; +end: \ No newline at end of file diff --git a/arden/examples/MLM Using While Loop.mlm b/arden/examples/MLM Using While Loop.mlm new file mode 100644 index 0000000000..11093b274f --- /dev/null +++ b/arden/examples/MLM Using While Loop.mlm @@ -0,0 +1,64 @@ +maintenance: +title: Allergy_test_with_while_loop;; +filename: test_for_allergies_while_loop;; +Arden: version 3;; +version: 0.00;; +institution: ;; +author: ;; +specialist: ;; +date: 1997-11-06;; +validation: testing;; +library: +purpose: +Illustrates the use of a WHILE-LOOP that processes an entire list +;; +explanation: +;; +keywords: +;; +knowledge: +type: data-driven;; +data: /* Receives four arguments from the calling MLM: */ +(med_orders, +med_allergens, +patient_allergies, +patient_reactions) := ARGUMENT; +;; +evoke: +;; +logic: /* Initializes variables */ +a_list:= (); +m_list:= (); +r_list:= (); +num:= 1; +/* Checks each allergen in the medications to determine */ +/* if the patient is allergic to it */ +while num <= (count med_allergen) do +allergen:= last(first num from med_allergens); +allergy_found:= (patient_allergies = allergen); +reaction:= patient_reactions where allergy_found; +medication:= med_orders where (med_allergens = allergen); +/* Adds the allergen, medication, and reaction to */ +/* variables that will be returned to the calling MLM */ +If any allergy_found then +a_list:= a_list, allergen; +m_list:= m_list, medication; +r_list:= r_list, reaction; +endif; +/* Increments the counter that is used to stop the while-loop */ +num:= num + 1; +enddo; +/* Concludes true if the patient is allergic to one of */ +/* the medications */ +If exist m_list then +conclude true; +endif; +;; +action: +/* Returns three lists to the calling MLM */ +return m_list, a_list, r_list; +;; +resources: +default: en;; +language: en;; +end: \ No newline at end of file diff --git a/arden/examples/Fifth.mlm b/arden/examples/MLM for Doses Calculation.mlm similarity index 92% rename from arden/examples/Fifth.mlm rename to arden/examples/MLM for Doses Calculation.mlm index 7fac9acb14..2d95fbe8c7 100644 --- a/arden/examples/Fifth.mlm +++ b/arden/examples/MLM for Doses Calculation.mlm @@ -1,7 +1,7 @@ maintenance: title: Doses Calculation Theophylline - fuzzy;; mlmname: dose_calculation_theophylline_fuzzy;; -arden: version 2.9;; +arden: version 3;; version: ;; institution: ;; author: ;; @@ -13,7 +13,7 @@ purpose: calculates the suggested daily doses based on the patients age;; explanation: ;; keywords: ;; citations: -1. refute "Some link"; +http://library.buffalo.edu/libraries/projects/cases/drug_dosing/drug_dosing_notes.html ;; knowledge: type: data_driven;; diff --git a/arden/examples/Management Suggestion Gentamicin.mlm b/arden/examples/Management Suggestion Gentamicin.mlm new file mode 100644 index 0000000000..0fe0926dcf --- /dev/null +++ b/arden/examples/Management Suggestion Gentamicin.mlm @@ -0,0 +1,77 @@ +maintenance: +title: Dosing for gentamicin in renal failure;; +mlmname: gentamicin_dosing;; +arden: Version 3;; +version: 1.00;; +institution: Columbia-Presbyterian Medical Center;; +author: George Hripcsak, M.D.;; +specialist: ;; +date: 1991-03-18;; +validation: testing;; +library: +purpose: +Suggest an appropriate gentamicin dose in the setting of renal +insufficiency. (This MLM demonstrates a management suggestion.);; +explanation: +Patients with renal insufficiency require the same loading dose of +gentamicin as those with normal renal function, but they require a +reduced daily dose. The creatinine clearance is calculated by serum +creatinine, age, and weight. If it is less than 30 ml/min, then an +appropriate dose is calculated based on the clearance. If the +ordered dose differs from the calculated dose by more than 20 %, +then an alert is generated.;; +keywords: gentamicin; dosing;; +citations: ;; +knowledge: +type: data-driven;; +data: /* an order for gentamicin evokes this MLM */ +gentamicin_order := event {medication_order where +class = gentamicin}; +/* gentamicin doses */ +(loading_dose, periodic_dose, periodic_interval) := +read last {medication_order initial dose, +periodic dose, interval}; +/* serum creatinine mg/dl */ +serum_creatinine := read last {serum_creatinine} +where it occurred within the past 1 week; +/* birthdate */ +birthdate := read last {birthdate}; +/* weight kg */ +weight := read last {weight} +where it occurred within the past 3 months; +;; +evoke: +gentamicin_order; +;; +logic: age := (now - birthdate) / 1 year; +creatinine_clearance := (140 - age) * (weight) / +(72 * serum_creatinine); +/* the algorithm can be adjusted to handle higher clearances */ +if creatinine_clearance < 30 then +calc_loading_dose := 1.7 * weight; +calc_daily_dose := 3 * (0.05 + creatinine_clearance / 100); +ordered_daily_dose := periodic_dose * +periodic_interval /(1 day); +/* check whether order is appropriate */ +if (abs(loading_dose - calc_loading_dose) / +calc_loading_dose > 0.2) +or +(abs(ordered_daily_dose - calc_daily_dose) / +calc_daily_dose > 0.2) then +conclude true; +endif; +endif; +;; +action: write "Due to renal insufficiency, the dose of gentamicin " || +"should be adjusted. The patient's calculated " || +"creatinine clearance is " || creatinine_clearance || +" ml/min. A single loading dose of " || +calc_loading_dose || " mg should be given, followed by " || +calc_daily_dose || " mg daily. Note that dialysis may " || +"necessitate additional loading doses."; +;; +urgency: 50;; +resources: +default: en;; +language: en;; +end: \ No newline at end of file diff --git a/arden/examples/Management Suggestion Granulocytopenia.mlm b/arden/examples/Management Suggestion Granulocytopenia.mlm new file mode 100644 index 0000000000..f3a665f026 --- /dev/null +++ b/arden/examples/Management Suggestion Granulocytopenia.mlm @@ -0,0 +1,58 @@ +maintenance: +title: Granulocytopenia and Trimethoprim/Sulfamethoxazole;; +mlmname: anctms;; +arden: Version 3;; +version: 2.00;; +institution: Columbia-Presbyterian Medical Center;; +author: George Hripcsak, M.D.;; +specialist: ;; +date: 1991-05-28;; +validation: testing;; +library: +purpose: +Detect granulocytopenia possibly due to +trimethoprim/sulfamethoxazole;; +explanation: +This MLM detects patients that are currently taking +trimethoprim/sulfamethoxazole whose absolute neutrophile count is +less than 1000 and falling.;; +keywords: +granulocytopenia; agranulocytosis; trimethoprim; sulfamethoxazole;; +citations: +1. Anti-infective drug use in relation to the risk of +agranulocytosis and aplastic anemia. A report from the +International Agranulocytosis and Aplastic Anemia Study. +Archives of Internal Medicine, May 1989, 149(5):1036-40.;; +links: "CTIM .34.56.78"; +"MeSH agranulocytosis/ci and sulfamethoxazole/ae";; +knowledge: +type: data-driven;; +data: +/* capitalized text within curly brackets would be replaced with */ +/* an institution's own query */ +let anc_storage be event {STORAGE OF ABSOLUTE_NEUTROPHILE_COUNT}; +let anc be read last 2 from {ABSOLUTE_NEUTROPHILE_COUNT} +where they occurred within the past 1 week; +let pt_is_taking_tms be read exist +{TRIMETHOPRIM_SULFAMETHOXAZOLE_ORDER}; +;; +evoke: anc_storage; +;; +logic: +if pt_is_taking_tms +and the last anc is less than 1000 +and the last anc is less than the first anc +/* is anc falling? */ +then +conclude true; +else +conclude false; +endif; +;; +action: write "Caution: patient's relative granulocytopenia may be " || +"exacerbated by trimethoprim/sulfamethoxazole."; +;; +resources: +default: en;; +language: en;; +end: \ No newline at end of file diff --git a/arden/examples/Monitoring.mlm b/arden/examples/Monitoring.mlm new file mode 100644 index 0000000000..23e109a1e2 --- /dev/null +++ b/arden/examples/Monitoring.mlm @@ -0,0 +1,69 @@ +maintenance: +title: Monitor renal function while taking gentamicin;; +mlmname: gentamicin_monitoring;; +arden: Version 3;; +version: 1.00;; +institution: Columbia-Presbyterian Medical Center;; +author: George Hripcsak, M.D.;; +specialist: ;; +date: 1991-03-19;; +validation: testing;; +library: +purpose: +Monitor the patient's renal function when the patient is taking +gentamicin. (This MLM demonstrates periodic monitoring.);; +explanation: +This MLM runs every five days after the patient is placed on +gentamicin until the medication is stopped. If the serum creatinine +has not been checked recently, then an alert is generated +requesting follow-up. If the serum creatinine has been checked, is +greater than 2.0, and has risen by more than 20 %, then an alert is +generated warning that the patient may be developing renal +insufficiency due to gentamicin.;; +keywords: gentamicin; renal function;; +citations: ;; +knowledge: +type: data-driven;; +data: +/* an order for gentamicin evokes this MLM */ +gentamicin_order := event {medication_order where +class = gentamicin}; +/* check whether gentamicin has been discontinued */ +gentamicin_discontinued := +read exist{medication_cancellation where class = gentamicin} +where it occurs after eventtime; +/* baseline serum creatinine mg/dl */ +baseline_creatinine := read last {serum_creatinine} +where it occurred before eventtime; +/* followup serum creatinine mg/dl */ +recent_creatinine := read last {serum_creatinine} +where it occurred within the past 3 days; +;; +evoke: every 5 days for 10 years starting 5 days after time of +gentamicin_order until gentamicin_discontinued; +;; +logic: if recent_creatinine is not present then +no_recent_creatinine := true; +conclude true; +elseno_recent_creatinine := false; +if % increase of (serum_creatinine, +recent_creatinine) > 20 /* % */ +and recent_creatinine > 2.0 then +conclude true; +endif; +endif; +;; +action: if no_recent_creatinine then +write "Suggest obtaining a serum creatinine to follow up " || +"on renal function in the setting of gentamicin."; +else +write "Recent serum creatinine (" || recent_creatinine || +" mg/dl) has increased, possibly due to renal " || +"insufficiency related to gentamicin use."; +endif; +;; +urgency: 50;; +resources: +default: en;; +language: en;; +end: \ No newline at end of file diff --git a/arden/examples/Second.mlm b/arden/examples/Research Study Screening.mlm similarity index 68% rename from arden/examples/Second.mlm rename to arden/examples/Research Study Screening.mlm index 1ed8f1b141..dbbdb7371f 100644 --- a/arden/examples/Second.mlm +++ b/arden/examples/Research Study Screening.mlm @@ -31,13 +31,15 @@ calcium := read last {‘06210519’,’06210669’;’CALCIUM’}; /* albumin in g/dL */ evoking_albumin := read last {‘06210669’;’ALBUMIN’ where evoking}; /* albumin in g/dL; not necessarily from same test as Ca */ -last_albumin := read last ({‘06210669’;’ALBUMIN’} -where it occurred within the past 2 weeks); +last_albumin := read last {‘06210669’;’ALBUMIN’} +where it occurred within the past 2 weeks; /* creatinine in mg/dL; not necessarily from same test as Ca */ -creatinine := read last ({‘06210669’,’06210545’,’06000545’;’CREAT’} -where it occurred within the past 2 weeks); +creatinine := read last {‘06210669’,’06210545’,’06000545’;’CREAT’} +where it occurred within the past 2 weeks; +;; +evoke: +storage_of_calcium; ;; -evoke: storage_of_calcium;; logic: /* make sure the Ca is present (vs. hemolyzed, ...) */ IF calcium is not present THEN conclude false; @@ -70,7 +72,7 @@ msg := msg || "; (total or corrected calcium " || "was at least 11.5)"; conclude true; -ELSE +ELSE conclude false; ENDIF; ENDIF; @@ -97,46 +99,10 @@ ENDIF; ENDIF; ENDIF; ;; -action: write "hypercalcemia study: " || msg;; -urgency: 50;; -end: - -maintenance: -title: Check for penicillin allergy;; -mlmname: pen_allergy;; -arden: version 3;; -version: 1.00;; -institution: Columbia-Presbyterian Medical Center;; -author: George Hripcsak, M.D.;; -specialist: ;; -date: 1991-03-18;; -validation: testing;; -library: -purpose: -When a penicillin is prescribed, check for an allergy. (This MLM -demonstrates checking for contraindications.);; -explanation: -This MLM is evoked when a penicillin medication is ordered. An -alert is generated because the patient has an allergy to penicillin -recorded.;; -keywords: penicillin; allergy;; -citations: ;; -knowledge: -type: data-driven;; -data: /* an order for a penicillin evokes this MLM */ -penicillin_order := event {medication_order where -class = penicillin}; -/* find allergies */ -penicillin_allergy := read last {allergy where -agent_class = penicillin}; -;; -evoke: penicillin_order;; -logic: -if exist(penicillin_allergy)then -conclude true; -endif; +action: write "hypercalcemia study: " || msg; ;; -action: write "Caution, the patient has the following allergy to penicillin documented:" -|| penicillin_allergy;; urgency: 50;; -end: +resources: +default: en;; +language: en;; +end: \ No newline at end of file diff --git a/arden/examples/SyntaxTest.mlm b/arden/examples/SyntaxTest.mlm new file mode 100644 index 0000000000..e9a2a3c577 --- /dev/null +++ b/arden/examples/SyntaxTest.mlm @@ -0,0 +1,1496 @@ +MAINTENANCE: +TITLE: A Syntax test for all the examples from the Arden Syntax standard;; +MLMNAME: SyntaxTest;; +ARDEN: version 3 ;; +VERSION: 1.00;; +INSTITUTION: Medexter GmbH;; +AUTHOR: Christian Weich, B.Sc cgw@medexter.com;; +SPECIALIST: Christian Weich, B.Sc cgw@medexter.com;; +DATE: 2024-06-19T14:30:23.26475+01:00;; +VALIDATION: testing;; +LIBRARY: +PURPOSE: This mlm is used to test all the examples given in the document: Arden Syntax +for medical Logic Systems Version 3.0 +HL7 Arden_E3.0_STU_2023DEC +Health Level Seven +Arden Syntax +Version 3.0;; +EXPLANATION: In the standard are many different examples provided for all the operators. +To prevent inconsistency and mistakes between the written text and the bnf grammar almost +all examples from the standard are in this mlm;; +KEYWORDS: "testing", inconsistency, "mistakes", bnf, ebnf;; +CITATIONS: 1. Refute "Arden Syntax for medical system 3.0"; +LINKS: +URL 'HL7 confluence' "https://confluence.hl7.org/display/ARD/Arden+Syntax+v3.0";; +KNOWLEDGE: +TYPE: data-driven;; +DATA: + +var := 0; +var := 345; +var := 0.1; +var := 34.5E34; +var := 0.1e-4; +var := .3; +var := 3.; +var := 3e10; +var := "this is a string"; +var := "this string has one quotation mark: "" "; +var := "this is a string with one space between 'with' and 'one'"; +var :="this is a string with + +one line break between 'with' and 'one'"; +var1 := null; +this_is_a_variable := true; +a := 345.4; +var := "this is a string"; +var := 1991-05-01T23:12:23; +var := 4 * cosine 5; +var1 := 7; +var := (4+3) * 73; + +/* explicit null */ +var := null; +/* division by zero */ +var := 3/0; +/* addition of Boolean */ +var := true + 3; + +Var := truth value 0; +Var := false; +Var := truth value 0.667; +Var := truth value 1; +Var := true; + +TwotoThree := fuzzy set (2, truth value 0), (2, truth value 1), (2, truth value 1), (3, truth value 1), (3, truth value 0); +TwotoThree := fuzzy set (2, truth value 0), (2, truth value 1), (3, truth value 1), (3, truth value 0); +OnetoFour := fuzzy set (1, truth value 0), (2, truth value 1), (2, truth value 1), (3, truth value 1), (4, truth value 0); +AfuzzyTime := today fuzzified by 1 day; +simple := 2009-10-10 fuzzified by 12 hours; +complex := fuzzy set (2009-10-10, truth value 0), (2009-10-11, truth value 1), (2009-11-10, truth value 1), (2009-11-11, truth value 0); +simple := 14 days fuzzified by 1 day; +complex := fuzzy set (2 days, truth value 0), (3 days, truth value 1), (14 days, truth value 1), (31 days, truth value 0); + +var := 4, 2; +var := (4, "a"), null; +var := , 3; +var := data1 MERGE data2; +var := (4, 3) MERGE (2, 1); + +var := SORT DATA data1; +var := REVERSE (SORT DATA data1); +var := SORT DATA (3, 1, 2, null); +var := SORT DATA (3, "abc"); +var := SORT TIME (); +var := SORT (1, 3, 2, 3); +var := SORT TIME data1; +var := SORT APPLICABILITY data1; +var := REVERSE (SORT APPLICABILITY data1); +var := SORT APPLICABILITY (3, 1, 2, null); +var := SORT APPLICABILITY (); + +var := sort var using it; // for sorting by data +var := sort var using time of it; // for sorting by time +var := sort var using sin it; // for sorting the list by +// the sin of each value +var := sort var using abs it; // for sorting the list by +// absolute values of the list elements +var := sort var using extract month it; // for sorting the +// list by month part of the list elements +var := sort var using it.height; // for sorting the objects by +// their field "height" +var := sort var using time of it.value; // for sorting the objects by the primary time of their field "value" + +var := ADD 4 TO (1, 2, 3); +var := ADD 4 TO (1, 2, 3) AT 1; +var := ADD null TO (1, 2, 3); +var := ADD 4 TO null; +var := ADD 4 TO (1, 2, 3) AT 9; +var := ADD 4 TO (1, 2, 3) AT (1, -1); +var := ADD 2 TO (1, 3, 4) AT INDEX OF 3 FROM (1, 3, 4); +var := ADD 4 TO (1, 2, 3) AT (1, 2); + +var := REMOVE 1 FROM (3, 2, 1); +var := REMOVE (1,3,6) FROM ("one", "two", 3, 4, 5, 6 days); +var := REMOVE null FROM (3, 2, 1); +var := REMOVE 8 FROM (3, 2, 1); +var := REMOVE (INDEX OF "3" FROM ("3", "3")) FROM ("3", "3"); +var := REMOVE 2 FROM null; +var := REMOVE 1 FROM null; +var := REMOVE () FROM (3, 2, 1); + +var := (10, 20, 30, 40) WHERE (true, false, true, 3); +var := (7.34, 7.38, 7.4) WHERE time of it is within 20 minutes following time of VentChange; +var := 1 WHERE true; +var := (1, 2, 3) WHERE true; +var := 1 WHERE (true, false, true); +var := (1, 2, 3, 4) WHERE (true, false, true); +var := queryResult where they are number; +var := queryResult where time of it is present; +post_prandial_blood_glucoses := bc_values where they occurred within 13:00:00 to 15:00:00; +var := labResults where day of week of time of them is in (SATURDAY, SUNDAY); + +include_valueset := NEW Valueset WITH [system:="https://fhir.loinc.org/ValueSet", code:="LL770-1"]; +fhir_observation := READ AS Observation WHERE it.code.coding.code IS IN include_valueset; + +RectType := OBJECT [x, y, width, height]; +Rect := new RectType; +var := Rect IS RectType; + +var := time of var IS NOT BEFORE 1990-03-05T11:11:11; +var := var OCCURRED NOT BEFORE 1990-03-05T11:11:11; +var := time of surgery IS WITHIN THE PAST 3 days; +var := surgery OCCURRED WITHIN THE PAST 3 days; +var := time(a) IS WITHIN 1990-03-05T11:11:11 TO time(b); +var := a OCCURRED WITHIN 1990-03-05T11:11:11 TO time(b); + +var := query_result OCCURRED EQUAL 1990-03-01T00:00:00; +var := query_result OCCURRED WITHIN 1990-03-01T00:00:00 TO 1990-03-11T00:00:00; +var := query_result OCCURRED WITHIN 3 days PRECEDING 1990-03-10T00:00:00; +var := query_result OCCURRED WITHIN 3 days FOLLOWING 1990-03-10T00:00:00; +var := query_result OCCURRED WITHIN 3 days SURROUNDING 1990-03-10T00:00:00; +var := request occurred within 2 hours surrounding 14:00; +var := measurements occurred within 30 minutes surrounding 13:00; +var := query_result OCCURRED WITHIN PAST 3 days; +var := query_result OCCURRED WITHIN SAME DAY AS 1990-03-08T01:01:01; +var := query_result OCCURRED WITHIN SAME DAY AS 01:01:01; +var := query_result OCCURRED BEFORE 1990-03-08T01:01:01; +var := query_result OCCURRED AFTER 1990-03-08T01:01:01; +var := query_result OCCURRED AT 1990-03-01T00:00:00; + +var := 2 days AFTER 1990-03-13T00:00:00; +var := 2 days BEFORE 1990-03-13T00:00:00; + +var := 2 days AGO; + +var := 2 days FROM 2000-09-11T00:08:00; + +var := TIME OF DAY OF 1990-01-03T14:23:17.3; +var := TIME OF DAY OF "this is not a time"; +/* let time of data0 be 2006-01-01T12:00:00 */ +var := TIME OF DAY OF (TIME OF data0); +var := TIME OF (TIME OF DAY OF (TIME OF data0)); + +var := DAY OF WEEK OF 2006-05-26T13:20:00; +var := DAY OF WEEK OF (TIME OF potassium); +var := DAY OF WEEK OF now; +var := DAY OF WEEK 15:30:00; +var := DAY OF WEEK OF 2006-05-26T13:20:00 = FRIDAY; +var := DAY OF WEEK OF TIME OF potassium IS IN (SATURDAY,SUNDAY); +var := DAY OF WEEK OF now IS IN (SATURDAY, SUNDAY); +weekend := DAY OF WEEK OF eventtime is in (SATURDAY, SUNDAY); +// weekend is true if the event occurred on Saturday or Sunday +weekday := ("Monday", "Tuesday", "Wednesday", "Sunday"); +last_k := last potassium; +last_k_time := time last_k; +msg := "The last potassium was collected on " +|| weekday[DAY OF WEEK OF last_k_time]; +//"The last potassium was collected on Tuesday" + +var := EXTRACT YEAR 1990-01-03T14:23:17.3; +var := EXTRACT YEAR (1 YEAR); +var := EXTRACT YEAR 14:23:17.3 +; +var := EXTRACT MONTH 1990-01-03T14:23:17.3; +var := EXTRACT MONTH 1; +var := EXTRACT MONTH 14:23:17.3; + +var := EXTRACT DAY 1990-01-03T14:23:17.3; +var := EXTRACT DAY "this is not a time"; +var := EXTRACT DAY 14:23:17.3; + +var := EXTRACT HOUR 1990-01-03T14:23:17.3; +var := EXTRACT HOUR (1 HOUR); +var := EXTRACT HOUR 14:23:17.3; + +var := EXTRACT MINUTE 1990-01-03T14:23:17.3; +var := EXTRACT MINUTE 1990-01-03; +var := EXTRACT MINUTE 0000-00-00; +var := EXTRACT MINUTE 14:23:17.3; + +var := EXTRACT SECOND 1990-01-03T14:23:17.3; +var := EXTRACT SECOND (1 second); +var := EXTRACT SECOND 14:23:17.3; + +var1 := 1990-03-15T15:00:00; +var := REPLACE YEAR OF var1 WITH 2011; +var := REPLACE YEAR OF var1 WITH (2011, 2010); +var := REPLACE YEAR OF var1 WITH -10; +var := REPLACE YEAR OF var1 WITH "7"; +var2 := 19:00:00; +var := REPLACE YEAR OF var2 WITH 2011; +var3 := (2010-09-21T16:30:00, 2010-03-15T15:00:00); +var := REPLACE YEAR OF var3 WITH 2011; +var3 := (2010-09-21T16:30:00, 2010-03-15T15:00:00); +var := REPLACE YEAR OF var3 WITH (1999, 2000); +var := REPLACE YEAR OF var3 WITH (1999, 2000, 2002); +var1 := 1990-03-15T15:00:00; + +var := REPLACE MONTH OF var1 WITH 11; +var := REPLACE MONTH OF var1 WITH (11, 10); +var := REPLACE MONTH OF var1 WITH 14; +var := REPLACE MONTH OF var1 WITH "7"; +var := REPLACE MONTH OF var1 WITH 7.45; +var2 := (2010-09-21T16:30:00, 2010-03-15T15:00:00); +var := REPLACE MONTH OF var2 WITH 12; +var3 := (2010-09-21T16:30:00, 2010-03-15T15:00:00); +var := REPLACE MONTH OF var3 WITH (6, 7); +var := REPLACE MONTH OF var3 WITH (3, 4, 7); + +var1 := 1990-03-15T15:00:00; +var := REPLACE DAY OF var1 WITH 11; +var := REPLACE DAY OF var1 WITH (11, 10); +var := REPLACE DAY OF var1 WITH 100; +var := REPLACE DAY OF var1 WITH "7"; +var := REPLACE DAY OF var1 WITH 7.45; +var := REPLACE DAY OF 1990-02-11T15:00:00 WITH 30; +var := REPLACE DAY OF 1990-02-11T15:00:00 WITH 0.8; +var := REPLACE DAY OF 1990-02-15T15:00:00 WITH 1.8; +var2 := (2010-09-21T16:30:00, 2010-03-15T15:00:00); +var := REPLACE DAY OF var2 WITH 7; +var3 := (2010-09-21T16:30:00, 2010-03-15T15:00:00); +var := REPLACE DAY OF var3 WITH (12, 23); +var := REPLACE DAY OF var3 WITH (12, 23, 24); + +var1 := 1990-03-15T15:00:00; +var := REPLACE HOUR OF var1 WITH 11; +var := REPLACE HOUR OF var1 WITH (11, 10); +var := REPLACE HOUR OF var1 WITH 100; +var := REPLACE HOUR OF var1 WITH "7"; +var := REPLACE HOUR OF 18:00 WITH 10; +var2 := (2010-09-21T16:30:00, 2010-03-15T15:00:00); +var := REPLACE HOUR OF var2 WITH 20; +var3 := (2010-09-21T16:30:00, 2010-03-15T15:00:00); +var := REPLACE HOUR OF var3 WITH (7, 9); +var := REPLACE HOUR OF var3 WITH (7, 9, 13); + +var1 := 1990-03-15T15:00:00; +var := REPLACE MINUTE OF var1 WITH 11; +var := REPLACE MINUTE OF var1 WITH (11, 10); +var := REPLACE MINUTE OF var1 WITH 100; +var := REPLACE MINUTE OF var1 WITH "7"; +var := REPLACE MINUTE OF 18:00 WITH 10; +var2 := (2010-09-21T16:30:00, 2010-03-15T15:00:00); +var := REPLACE MINUTE OF var2 WITH 15; +var3 := (2010-09-21T16:30:00, 2010-03-15T15:00:00); +var := REPLACE MINUTE OF var3 WITH (25, 23); +var := REPLACE MINUTE OF var3 WITH (25, 23, 7); + +var1 := 1990-03-15T15:00:00; +var := REPLACE SECOND OF var1 WITH 11; +var := REPLACE SECOND OF var1 WITH (11, 10); +var := REPLACE SECOND OF var1 WITH -100; +var := REPLACE SECOND OF var1 WITH "7"; +var := REPLACE SECOND OF 18:00 WITH 10; +var2 := (2010-09-21T16:30:00, 2010-03-15T15:00:00); +var := REPLACE SECOND OF var2 WITH 33; +var3 := (2010-09-21T16:30:00, 2010-03-15T15:00:00); +var := REPLACE SECOND OF var3 WITH (23, 42); +var := REPLACE SECOND OF var3 WITH (23, 42, 55); + +var := NEAREST (2 days ago) FROM datas; +var := NEAREST (2 days ago) FROM (3, 4); +var := NEAREST (2 days ago) FROM (); +var := NEAREST 12:00 FROM datas; +// the same as NEAREST 1990-03-18T12:00:00 +var := NEAREST 23:00 FROM datas; +// the same as NEAREST 1990-03-18T23:00:00 + +var := NEAREST 12:00 FROM query_result; + +var := NEAREST 12:30 FROM query_result; + +var := INDEX NEAREST (2 days ago) FROM datas; +var := INDEX NEAREST (2 days ago) FROM (3, 4); + +var := INDEX OF 4 FROM (1, 2, 3, 4, "5", "six", 7); +var := INDEX OF "5" FROM (1, 2, 3, 4, "5", "six", 7); +var := INDEX OF 5 FROM (1, 2, 3, 4, "5", "six", 7); +var := INDEX OF null FROM (1, 2, 3, 4, "5", "six", 7); +var := INDEX OF 5 FROM null; +var := INDEX OF null FROM null; +var := INDEX OF 5 FROM 5; +var := INDEX OF 1 FROM (1, 2, 1, 4, 1, "six", 7); +var := INDEX OF null FROM (1, 2, null, 4, null, "six", 7); + +var := AT LEAST 1 IsTrue FROM (TRUE, TRUE, FALSE, FALSE); +var := AT LEAST 2 AreTrue FROM (TRUE, TRUE, TRUE, FALSE); +var := AT LEAST 2 FROM (TRUE, FALSE, FALSE, FALSE); +var := AT LEAST 7 AreTrue FROM (TRUE, FALSE, FALSE); +var := AT LEAST 2 YEARS FROM (TRUE, FALSE, FALSE); +var := AT LEAST 2 FROM (TRUE, "true", FALSE); + +var := AT LEAST 2 OF (TRUE, truth value 0.7, truth value 0.1, FALSE); +var := APPLICABILITY OF (AT LEAST 2 OF (TRUE, truth value 0.7, FALSE)); +var := AT LEAST 7 OF (TRUE, truth value 0.1,FALSE); +var := AT LEAST 2 YEARS OF (TRUE, truth value 0.1,FALSE); +var := AT LEAST 2 OF (TRUE, "true", truth value 0.1,FALSE); +var := APPLICABILITY OF (AT LEAST 2 OF (TRUE, "true", truth value 0.1,FALSE)); + +var := AT MOST 2 AreTrue FROM (TRUE, TRUE, FALSE, FALSE); +var := AT MOST 1 IsTrue FROM (TRUE, TRUE, TRUE, FALSE); +var := AT MOST 2 FROM (TRUE, FALSE, FALSE, FALSE); +var := AT MOST 7 FROM (TRUE, FALSE, FALSE); +var := AT MOST 2 YEARS FROM (TRUE, FALSE, FALSE); +var := AT MOST 2 FROM (TRUE, "true", FALSE); + +var := AT MOST 2 OF (TRUE, truth value 0.4, truth value 0.7, FALSE); +var := APPLICABILITY OF (AT MOST 2 OF (TRUE, truth value 0.5, truth value 0.7, truth value 0.1, FALSE)); +var := AT MOST 7 OF (TRUE, truth value 0.5, FALSE); +var := AT MOST 2 YEARS OF (TRUE, 0.5, 0.7, 0.1, FALSE); +var := AT MOST 2 OF (TRUE, "true", 0.7, 0.1, FALSE); +var := APPLICABILITY OF (AT MOST 2 OF (TRUE, "true", 0.7, 0.1, FALSE)); + +var := SLOPE datas; +var := SLOPE (3, 4); + +var := TIME OF data0; +var := TIME TIME data0; +var := TIME (3, 4); + +var := time data2; + +LabResult := OBJECT [id, value]; +result := new LabResult; +result.id := 123; +time of result.id := 2004-01-16T00:00:00; +result.value := 1.0; +time of result.value := 2004-01-16T00:00:00; +var := time of result; // all attributes have same primary time +var := time of result.id; +time of result.id := 2004-01-17T00:00:00; +var := time of result; // primary times differ +var := time of result.id; + +var := now ATTIME 15:00:00; +var := TIME OF intuitive_new_millenium ATTIME 14:30:00; + +NameType := object [FirstName, LastName]; +/* Assume namelist contains a list of 2 NameType objects */ +var := namelist.FirstName; +var := namelist.LastName; +var := namelist[1].FirstName; +var := namelist[1].Height; +var := namelist.Height; + +chemistry_panel := object [albumin, calcium, phosphorus]; +/* assume patientResult is a single chemistry_panel object with albumin = 4.0 +mg/dL, calcium = 8.7 mg/dL and phosphorus = 3.0 mg/dL on 15 December 2004*/ +calciumPhosphorusProduct := patientResult.calcium * patientResult.phosphorus; +var := calciumPhosphorusProduct; +var := time of patientResult.calcium; + +PatientInfo := object [Name, Birthdate]; +/* Assume patient contains an object of type PatientInfo, and the Nameattribute contains an object of type NameType */ +var := patient.Name.FirstName; + +var := CLONE OF 1990-03-15T15:00:00; +var := CLONE (1, 2, someObject); +var := CLONE null; + +MedicationDose := OBJECT [Medication, Dose, Status]; +dose := NEW MedicationDose with "Ampicillin", "500mg", "Active"; +dose_attributes := extract attribute names dose; +dose_attributes := ("Medication", "Dose", "Status"); + +MedicationDose := OBJECT [Medication, Dose, Status]; +dose := NEW MedicationDose with "Ampicillin", "500mg", "Active"; +medication_name := attribute "Medication" from dose; +medication_name := "Ampicillin"; + +medication_name := dose.Medication; +medication_name := "Ampicillin"; +dose_attributes := extract attribute names dose; +medication_name := attribute dose_attributes[1] from dose; +medication_name := "Ampicillin"; + +LabResult := OBJECT [id, value]; +result := new LabResult; +result.id := 123; +APPLICABILITY of result.id := TRUTH VALUE 0.44; +result.value := 1.0; +APPLICABILITY of result.value := TRUTH VALUE 0.44; +var := APPLICABILITY of result; // all attributes have same applicability +var := APPLICABILITY of result.id; +APPLICABILITY of result.id := TRUTH VALUE 0.5; +var := APPLICABILITY of result; // applicabilities differ +var := APPLICABILITY of result.id; + +Rectangle := Object [Bottom, Top, Width, Height]; +message_type := OBJECT [id, msg]; +my_collection_type := OBJECT [name, message_list]; + +/* Define find_allergies MLM */ +find_allergies := MLM 'find_allergies'; + +/* Define find_allergies external function*/ +find_allergies := INTERFACE {\\RuleServer\AllergyRules\my_institution\find_allergies.exe}; + +MedicationDose := OBJECT [Medication, Dose, Status]; + +obj_def := object [x, y, z]; + +var1 := READ {select potassium from results where specimen = `serum`}; +var1 := READ last {select potassium from results}; +LET var1 BE READ {select potassium from results} WHERE it occurred within the +past 1 week; +var1 := READ first 3 from {select potassium from results} WHERE it occurred +within the past 1 week; +LET var1 BE READ {select potassium from results} WHERE it >= 3.4 AND it +occurred within the past 1 week; +birthdate := READ last {select birthdate from demographics}; +(Na, Cl, HCO3) := read last 3 from {select sodium, chloride, bicarb from electro}; +anion_gap := Na - (Cl + HCO3); +MedicationDose := object [Medication, Dose, Status]; +med_doses := read as MedicationDose {select med, dosage, status from client where status != "inactive"}; + +/* in this example the data to calculate three anion gaps are retrieved */ +(Na, Cl, HCO3) := read last 3 from {select sodium, chloride, bicarb from +electro}; +/* using READ AS */ +AnionGap := Object [Na, Cl, HCO3]; +gaps := read as AnionGap last 3 from {select sodium, chloride, bicarb from +electro}; + +exam_valueset := NEW Valueset WITH [system:="https://fhir.loinc.org/ValueSet", code:= "LL1162-8"]; +fhir_observations := READ AS Observation WHERE it.code.coding.code IS IN exam_valueset; + +event1 := EVENT {storage of serum potassium}; + +LET MLM1 BE MLM 'my_mlm1'; +mlm2 := MLM 'my_mlm2.mlm' FROM INSTITUTION "my institution"; + +mlm1 := MLM 'mlm_to_be_called'; +mlm2 := MLM 'diagnosis_score' FROM INSTITUTION "LDS Hospital"; + +var1 := CALL my_mlm WITH param1, (item1, item2); +(arg1, list1) := ARGUMENT; + +message1 := MESSAGE {pneumonia~23 45 65}; + +message_obj := OBJECT [subject, text]; +high_PTT_msg := MESSAGE AS message_obj {Elevated PTT}; +def_msg := MESSAGE AS message_obj; // default mapping clause + +destination1 := DESTINATION {email: user@cuasdf.bitnet}; +destination2 := DESTINATION {attending_physician(Pt_id)}; +destination3 := DESTINATION {"primary physician email"}; + +dest_obj := object [dest_method, recip_name, recip_address]; +email_attending := DESTINATION AS dest_obj {Attending Phys Email}; +def_destination := DESTINATION AS dest_obj; + +/* Declares the third-party drug-drug interaction function */ +/* The implementation within the {}-braces shows that a string (char*) +will be returned */ +/* when the third-party API (ThirdPartyAPI) is used to call */ +/* the drug-drug interaction function (DrugDrugInteraction) */ +/* The function expects that two medicaion strings (char*, char*) will be +passed */ +func_drugint := INTERFACE { +char* ThirdPartyAPI:DrugDrugInteraction (char*, char*) +}; + +/* Calls the drug-drug interaction function */ +alert_text := call func_drugint with "terfenadine", "erythromycin"; + +MedicationDose := OBJECT [Medication, Dose, Status]; + +RangeOfAge := linguistic variable [young, middleAge, old]; +Age := new RangeOfAge; +Age.young := FUZZY SET (0 years, truth value 1), (25 year, truth value 1), (35 years, truth value 0); +Age.middleAge := FUZZY SET(25 years, truth value 0), (35 years, truth value 1), (55 years, truth value 1), (65 years, truth value 0); +Age.old := FUZZY SET (55 years, truth value 0), (65 years, truth value 1); + +mlm2 := MLM 'my_mlm2.mlm' FROM INSTITUTION "my institution"; +INCLUDE mlm2; + +penicillin_storage := event {store penicillin order}; +cephalosporin_storage := event {store cephalosporin order}; + +;; +PRIORITY: 50.0 ;; +EVOKE: + +penicillin_storage; +penicillin_storage OR cephalosporin_storage; +ANY OF (penicillin_storage, cephalosporin_storage, aminoglycoside_storage); + +penicillin_storage OR cephalosporin_storage; + +TODAY ATTIME 15:00 AFTER TIME OF penicillin_storage; + +TOMORROW ATTIME 02:30 AFTER TIME OF penicillin_storage; + +MONDAY ATTIME 13:00 AFTER TIME OF penicillin_storage; + +MONDAY ATTIME 13:00 OR FRIDAY ATTIME 12:00 AFTER TIME OF penicillin_storage; + +3 days after time of penicillin_storage; +1992-01-01T00:00:00 AFTER TIME OF penicillin_storage; +TOMORROW ATTIME 02:00 AFTER TIME OF penicillin_storage; + +TOMORROW ATTIME 13:00 OR TOMORROW ATTIME 02:00 AFTER TIME OF penicillin_storage; + +TOMORROW ATTIME 02:30; + +20 hours; + +1992-01-01T00:00:00; +3 days AFTER 2007-01-01; +TOMORROW ATTIME 02:30; + +TODAY ATTIME 13:00 OR TOMORROW ATTIME 02:00; + +EVERY 1 day FOR 14 days STARTING time of event2; + +every 1 day for 14 days starting 1992-01-01T00:00:00 after time of event1; +every 1 day for 14 days starting time of event2; +every 2 hours for 1 day starting today attime 12:00 after time of event3; +every 1 week for 1 month starting 3 days after time of event4 until last(serum_potassium) > 5.0; + +EVERY 1 DAY FOR 5 months STARTING 2008-10-01T06:30:00; + +every 1 day for 14 days starting 1992-01-01T00:00:00; +every 2 hours for 1 day starting today attime 12:00; +every 1 week for 1 month starting 3 days after 1992-01-01T00:00:00 until last(serum_potassium) > 5.0; + +;; +LOGIC: +/* this assigns 0 to variable "var1" */ +let var1 be 0; +/* this causes the MLM named "hyperkalemia" to be executed */ +hyperkalemia_present := call hyperkalemia; +/* this concludes "true" if the potassium is greater than 5 */ +if potassium > 5.0 then +conclude true; +endif; +last_potas := last potas_list; +if last_potas > 5.0 then +conclude true; +endif; + +if latest potas > 5.0 then +conclude true; +endif; + +if time of latest potas is within past 3 days then +conclude true; +endif; + +var := true OR false; +var := false OR false; +var := true OR null; +var := false OR null; +var := false OR 3.4; +var := false OR (0.4 AS TRUTH VALUE); //see section 9.20.4 (as truth value) +var := true OR (TRUTH VALUE 0.7); //see section 8.13 (truth values) +var := (0.5 AS TRUTH VALUE) OR (0.4 AS TRUTH VALUE); +var := (true, false) OR (false, true); +var := () OR (); + +var := true AND false; +var := true AND null; +var := false AND (0.4 AS TRUTH VALUE); //see section 9.20.4 (as truth value); +var := false AND (TRUTH VALUE 0.5); //see section 8.13 (truth values); +var := (0.5 AS TRUTH VALUE) AND (0.4 AS TRUTH VALUE); +var := false AND null; + +var := NOT false; +var := NOT null; +var := NOT (0.2 as TRUTH VALUE); //see section 9.20.4 (as truth value) +var := NOT (TRUTH VALUE 0.2); //see section 8.13 (truth values) +var := NOT (false, true); +var := NOT (); + +var := 1 = 2; +var := (1, 2, "a") = (null, 2, 3); +var := (3/0) = (3/0); +var := 5 = (); +var := (1, 2, 3) = (); +var := null = (); +var := () = (); +var := 5 = null; +var := (1, 2, 3) = null; +var := null = null; +var := (1, 2, 3) = (1, 2, 4); +var := 1979-02-25T08:20:00 = 08:20:00; + +var := 1 <> 2; +var := (1, 2, "a") <> (null, 2, 3); +var := (3/0) <> (3/0); +var := 1979-02-25T08:20:00 <> 08:20:00; + +var := 1 < 2; +var := 1990-03-02T00:00:00 < 1990-03-10T00:00:00; +var := 1990-03-02T00:00:00 < 13:00:00; +var := 13:00:00 < 14 hours; +var := 2 days < 1 year; +var := "aaa" < "aab"; +var := "aaa" < 1; + +var := 1 <= 2; +var := 1990-03-02T00:00:00 <= 1990-03-10T00:00:00; +var := 1990-03-02T00:00:00 <= 13:00:00; +var := 2 days <= 1 year; +var := "aaa" <= "aab"; +var := "aaa" <= 1; + +young := FUZZY SET (0, truth value 1),(15, truth value 1),(20, truth value 0); +middle_aged := FUZZY SET (15, truth value 0),(20, truth value 1),(60, truth value 1), (70, truth value 0); +var := 25 <= young; +var := 25 <= middle_aged; +var := 10 <= young; +var := 10 <= middle_aged; +var := 17.5 <= young; +var := 17.5 <= middle_aged; + +var := 1 > 2; +var := 1990-03-02T00:00:00 > 1990-03-10T00:00:00; +var := 1990-03-02T00:00:00 > 13:00:00; +var := 2 days > 1 year; +var := "aaa" > "aab"; +var := "aaa" > 1; + +var := 1 >= 2; +var := 1990-03-02T00:00:00 >= 1990-03-10T00:00:00; +var := 1990-03-02T00:00:00 >= 13:00:00; +var := 2 days >= 1 year; +var := "aaa" >= "aab"; +var := "aaa" >= 1; + +young := FUZZY SET (0, truth value 1), (15, truth value 1), (20, truth value 0); +middle_aged := FUZZY SET (15, truth value 0), (20, truth value 1), (60, truth value 1), (70, truth value 0); +var := 25 >= young; +var := 25 >= middle_aged; +var := 10 >= young; +var := 10 >= middle_aged; +var := 17.5 >= middle_aged; +var := 17.5 >= young; + +var := Fuzzy Set (0, truth value 0), (4, truth value 1), (5, truth value 0); +crispVar := 2; +var := 4 IS IN (5 fuzzified by 2); +var := 2 IS IN (Fuzzy Set (0, truth value 0), (4, truth value 1),(5, truth value 0)); + +var := null || 3; +var := 4 || 5; +var := 4.7 || "four"; +var := true || ""; +var := 3 days || " left"; +var := "on " || 1990-03-15T13:45:01; +var := "list=" || (1, 2, 3); + +var := (1, 2, 3) formatted with "%2.2d::%2.2d::%2.2d"; +var := 10.60528 formatted with "The result was %.2f mg"; +var := 1998-01-10T17:25:00 formatted with "The date was %.2t"; +var := 1998-01-10T17:25:00 formatted with "The year was %.0t"; +/* longer example */ +a := "ten"; +b := "twenty"; +c := "thirty"; +f := "%s, %s, %s or more"; +var := (a, b, c) formatted with f; + +var := STRING ("a", "b", "c"); +var := STRING ("a", "bc"); +var := STRING (); +var := STRING REVERSE EXTRACT CHARACTERS "abcde"; + +var := "fatal heart attack" MATCHES PATTERN "%heart%"; +var := "fatal heart attack" MATCHES PATTERN "heart"; +var := "abnormal values" MATCHES PATTERN "%value_"; +var := "fatal pneumonia" MATCHES PATTERN "%pulmonary%"; +var := ("stunned myocardium", "myocardial infarction") MATCHES PATTERN "%myocardium"; +var := "5%" MATCHES PATTERN "_\%"; + +var := LENGTH OF "Example"; +var := LENGTH "Example String"; +var := LENGTH ""; +var := LENGTH (); +var := LENGTH OF null; +var := LENGTH OF ("Negative", "Pos", 2); + +var := UPPERCASE "Example String"; +var := UPPERCASE ""; +var := UPPERCASE null; +var := UPPERCASE (); +var := uppercase ("5-Hiaa", "Pos", 2); + +var := LOWERCASE "Example String"; +var := LOWERCASE ""; +var := LOWERCASE 12.8; +var := LOWERCASE null; +var := LOWERCASE ("5-HIAA", "Pos", 2); + +var := TRIM " example "; +var := TRIM ""; +var := TRIM (); +var := TRIM LEFT " result: "; +var := TRIM RIGHT " result: "; +var := TRIM (" 5 N", "2 E ", 2); + +var := FIND "a" IN STRING "Example Here"; +var := FIND "ple" IN STRING "Example Here"; +var := FIND "s" IN STRING "Example Here"; +var := FIND 2 IN STRING "Example Here"; +var := FIND "a" STRING 510; +var := FIND "t" STRING ("start", "meds", "halt"); +var := FIND "e" IN STRING "Example Here" STARTING AT 1; +var := FIND "e" IN STRING LOWERCASE "Example Here" STARTING AT 1; +var := FIND "e" IN STRING "Example Here" STARTING AT 8; +var := FIND "e" IN STRING "Example Here" STARTING AT 10; +var := FIND "e" IN STRING "Example Here" STARTING AT 11; +var := FIND "e" IN STRING "Example Here" STARTING AT 13; +var := FIND "e" IN STRING "Example Here" STARTING AT 1.5; +var := FIND "e" IN STRING "Example Here" STARTING AT "x"; +var := FIND "e" IN STRING "Example Here" STARTING AT (10, 11); + +var := SUBSTRING 2 CHARACTERS FROM "abcdefg"; +var := SUBSTRING 100 CHARACTERS FROM "abcdefg"; +var := SUBSTRING 3 CHARACTERS STARTING AT 4 FROM "abcdefg"; +var := SUBSTRING 20 CHARACTERS STARTING AT 4 FROM "abcdefg"; +var := SUBSTRING 2.3 CHARACTERS FROM "abcdefg"; +var := SUBSTRING 2 CHARACTERS STARTING AT 4.7 FROM "abcdefg"; +var := SUBSTRING 3 CHARACTERS STARTING AT "c" FROM "abcdefg"; +var := SUBSTRING "b" CHARACTERS STARTING AT 4 FROM "abcdefg"; +var := SUBSTRING 3 CHARACTERS STARTING AT 4 FROM 281471; +var := SUBSTRING 1 CHARACTERS STARTING AT 4 FROM "abcdefg"; +var := SUBSTRING -1 CHARACTERS STARTING AT 4 FROM "abcdefg"; +var := SUBSTRING -3 CHARACTERS STARTING AT 4 FROM "abcdefg"; +var := SUBSTRING 1 CHARACTERS FROM "abcdefg"; +var := SUBSTRING -1 CHARACTERS STARTING AT LENGTH OF "abcdefg" FROM "abcdefg"; +var := SUBSTRING 3 CHARACTERS FROM ("Positive", "Negative", 2); + +bp := "121/86"; +slash_pos := FIND "/" IN STRING bp; +systolic := SUBSTRING (slash_pos - 1) CHARACTERS FROM bp; +systolic := SUBSTRING -3 CHARACTERS STARTING AT (slash_pos - 1) FROM bp; +diastolic := SUBSTRING 3 CHARACTERS STARTING AT (slash_pos + 1) FROM bp; +diastolic := SUBSTRING (LENGTH of bp) CHARACTERS STARTING AT (slash_pos + 1) FROM bp; + +var := localized 'msg'; +var := creat formatted with localized 'creat'; +var := localized 'unknown'; + +var := localized 'msg' by "en_US"; +var := creat formatted with localized 'creat' by lang_setting; /* lang_setting == "de" */ + +var := 2 YEAR; + +var := MINIMUM 2 FROM (11, 14, 13, 12); +var := MINIMUM 2 FROM 3; +var := MINIMUM 2 FROM (3, "asdf"); +var := MINIMUM 2 FROM (); +var := MINIMUM 0 FROM (2, 3); +var := MINIMUM 3 FROM (3, 5, 1, 2, 4, 2); + +var := MAXIMUM 2 FROM (11, 14, 13, 12); +var := MAXIMUM 2 FROM 3; +var := MAXIMUM 2 FROM (3, "asdf"); +var := MAXIMUM 2 FROM (); +var := MAXIMUM 0 FROM (1, 2, 3); +var := MAXIMUM 3 FROM (1, 5, 2, 4, 1, 4); + +var := FIRST 2 FROM (11, 14, 13, 12); +var := FIRST 2 FROM 3; +var := FIRST 2 FROM (null, 1, 2, null); +var := FIRST 2 FROM (); + +var := LAST 2 FROM (11, 14, 13, 12); +var := LAST 2 FROM 3; +var := LAST 2 FROM (null, 1, 2, null); +var := LAST 2 FROM (); + +var := SUBLIST 2 ELEMENTS FROM (1, 2, 3, 4, 5); +var := SUBLIST 100 ELEMENTS FROM (1, 2, 3, 4, 5); +var := SUBLIST 3 ELEMENTS STARTING AT 4 FROM (1, 2, 3, 4, 5, 6, 7); +var := SUBLIST 20 ELEMENTS STARTING AT 4 FROM (1, 2, 3, 4, 5, 6, 7); + +var := SUBLIST 2.3 ELEMENTS FROM (1, 2, 3, 4, 5, 6, 7); +var := SUBLIST 2 ELEMENTS STARTING AT 4.7 FROM (1, 2, 3, 4, 5, 6, 7); +var := SUBLIST 3 ELEMENTS STARTING AT "c" FROM (1, 2, 3, 4, 5, 6, 7); +var := SUBLIST "b" ELEMENTS STARTING AT 4 FROM (1, 2, 3, 4, 5, 6, 7); +var := SUBLIST 3 ELEMENTS STARTING AT 4 FROM 281471; +var := SUBLIST 1 ELEMENTS STARTING AT 4 FROM (1, 2, 3, 4, 5, 6, 7); +var := SUBLIST -1 ELEMENTS STARTING AT 4 FROM (1, 2, 3, 4, 5, 6, 7); +var := SUBLIST -3 ELEMENTS STARTING AT 4 FROM (1, 2, 3, 4, 5, 6, 7); +var := SUBLIST 1 ELEMENTS FROM (1, 2, 3, 4, 5, 6, 7); + +var := INCREASE (11, 15, 13, 12); +var := INCREASE 3; +var := INCREASE (); +var := INCREASE (1990-03-01, 1990-03-02); +var := INCREASE (13:00:00, 14:00:00); +var := INCREASE (1 day, 2 days); +var := DECREASE (11, 15, 13, 12); +var := DECREASE 3; +var := DECREASE (); +var := DECREASE (1990-03-01, 1990-03-02); +var := DECREASE (13:00:00, 14:00:00); +var := DECREASE (1 day, 2 days); + +var := % INCREASE (11, 15, 13); +var := % INCREASE 3; +var := % INCREASE (); +var := % INCREASE (1 day, 2 days); + +var := % DECREASE (11, 15, 13); +var := % DECREASE 3; +var := % DECREASE (); +var := % DECREASE (1 day, 2 days); + +var := EARLIEST 2 FROM (); + +var := LATEST 2 FROM (); + +var := INDEX MINIMUM 2 FROM (11, 14, 13, 12); +var := INDEX MINIMUM 3 FROM (3, 5, 1, 2, 4, 2); +var := INDEX MIN 2 FROM (3, "asdf"); +var := INDEX MINIMUM 2 FROM 3; +var := INDEX MINIMUM 0 FROM (2,3); + +var := INDEX MAXIMUM 2 FROM (11, 14, 13, 12); +var := INDEX MAXIMUM 3 FROM (3, 5, 1, 2, 4, 2); + +var := INDEX MAXIMUM 2 FROM 3; +var := INDEX MAXIMUM 0 FROM (2, 3); + +Var1 := fuzzy set (2, truth value 0), (3, truth value 1), (4, truth value 1), (5, truth value 0); +Var2 := fuzzy set ((now - 2 days), truth value 0), (now, truth value 1), ((now + 1 day), truth value 0); +Var3 := fuzzy set (2001-12-12, truth value 0), (2003-12-12, truth value 1), (2009-01-01, truth value 0); +Var4 := fuzzy set (2 days, truth value 0), (3 days, truth value 1), (4 days, truth value 1), (5 days, truth value 0); + +Var1 := 7 fuzzified by 2; +Var2 := now fuzzified by 2 days; +Var3 := 7 days fuzzified by 2 hours; + +var := Defuzzified (7 fuzzified by 2); +var := APPLICABILITY OF data0; +var := APPLICABILITY APPLICABILITY data0; +var := APPLICABILITY (3, 4); + +APPLICABILITY data1 := TRUTH VALUE 0.44; + +var1 := 1; +var1 := 3; +var2 := var1 + 2; + + +rect := new Rectangle; +// assign attributes +rect.Bottom := 0; +rect.Top := 0; +rect.Width := 10; +rect.Height := 20; +// incorrect assignment +rect.Depth := 30; +var := rect.Depth; + +rect1 := new Rectangle; +// assign attributes +rect1.Bottom := 0; +rect1.Top := 0; +rect1.Width := 10; +rect1.Height := 20; +rect2 := rect1; // references the same Rectangle +rect1.Width := 50; +var := rect2.Width; // rect2.width reflects change to shared object + +//simple example using index +my_list := 5, 10, 15; +my_list[3] := 20; //contents of my_list are now 5, 10, 20 +//create one object with three nested objects +message_list := (); +for i in 1 seqto 3 do +message_text := new message_type with i, "this is message " || i; +message_list := message_list, message_text; +enddo; +my_obj := new my_collection_type with "Reminders", message_list; +//traditional syntax +n := 2; +obj1 := my_obj.message_list[n]; +obj1.msg := "this is a replacement message"; +message2 := new message_type with 10, "this is message 10"; +my_obj.message_list := first (n-1) from my_obj.message_list, +message2, last (count of my_obj.message_list - n) from +my_obj.message_list; +var1 := first (n-1) from my_obj.message_list; +var2 := last (count of my_obj.message_list - n) from my_obj.message_list; +//enhanced syntax +n := 2; +my_obj.message_list[n].msg := "this is a replacement message"; //modify nth item + +my_obj.message_list[n] := new message_type with 10, "this is message 10"; +//replace nth item +//additional examples +my_obj.message_list.msg := "This is a test"; //modifies message in all objects +my_var := my_obj.message_list.msg; //contents of my_var are "This is a test", "This is a test", "This is a test" +my_list[1] := my_var; //contents of my_list changed to "This is a test", "This is a test", "This is a test", 10, 20 + +Var := 0; +Con := truth value 0.2; +If con then +Var := Var + 1; +Else +Var := Var + 3; +Endif; + +Var := 0; +Bool_true := true; +Con := truth value 0.2; +con_second := truth value 0.3; +IF Con THEN +Var := Var + 1; +IF con_second THEN +Var := Var + 1; +ELSE +Var := Var + 3; +ENDIF; +ELSE +Var := Var + 3; +ENDIF; +CONCLUDE TRUE; + +Var := 0; +Bool_true := true; +Con := truth value 0.2; +IF Con THEN +Var := Var + 1; +CONCLUDE FALSE; +ELSE +Var := Var + 3; +ENDIF; +CONCLUDE TRUE; + +Var := 0; +Bool_true := true; +Con := truth value 0.2; +IF Con THEN +Var := Var + 1; +ELSE +Var := Var + 3; +ENDIF AGGREGATE; +CONCLUDE TRUE; + +IF var1 THEN +var2 := 0; +ELSE +var2 := 45; +ENDIF; +IF not(var1) THEN +var2 := 45; +ELSE +var2 := 0; +ENDIF; + +IF var1 is Boolean THEN +IF var1 THEN +var2 := "var1 is true"; +ELSE +var2 := "var1 is false"; +ENDIF; +ELSE +var2 := "var1 is null or some other type"; +ENDIF; + +IF any(Bool_list) THEN +var2 := 0; +ENDIF; + +switch inVal +case 1 +returnVal := 7; +case 2 +returnVal := 9; +endswitch; + +age := 16; +young := FUZZY SET (0, truth value 1), (15, truth value 1), (20, truth value 0); +middle_aged := FUZZY SET (15, truth value 0), (20, truth value 1), (60, truth value 1), (70, truth value 0); +dose := 0; +switch age +case young +dose := 10; +case middle_aged +dose := 20; +endswitch; + +switch inVal +case 1 +returnVal := 7; +case 2 +returnVal := 9; +default +returnVal := 0; //error state +endswitch; + +age := 16; +young := FUZZY SET (0, truth value 1), (15, truth value 1), (17, truth value 0); +middle_aged := FUZZY SET (15, truth value 0), (20, truth value 1), (60, truth value 1), (70, truth value 0); +dose := 0; +switch age +case young +dose := 10; +case middle_aged +dose := 20; +default +dose := 15; +endswitch; + +age := 16; +young := FUZZY SET (0, truth value 1), (15, truth value 1), (17, truth value 0); +middle_aged := FUZZY SET (15, truth value 0), (20, truth value 1), (60, truth value 1), (70, truth value 0); +dose := 0; +switch age +case young +dose := 10; +case middle_aged +dose := 20; +default +dose := 15; +endswitch aggregate; + +CONCLUDE false; +CONCLUDE potas > 5.0; + +x := CALL xxx with (a, b), (c merge d), e + f; +y := CALL yyy WITH expr1, expr2; +z := CALL zzz WITH (expr3, expr4); +var1 := CALL my_mlm1 WITH param1, param2; +(var2, var3, var4) := CALL my_mlm2 WITH param1, param2; +var1 := CALL my_event WITH param1, param2; +var1 := CALL my_interface_function1 WITH param1, param2; +(var1, var2, var3) := CALL my_interface_function2 WITH param1, param2; + +/* Lists two medications and their allergens */ +med_orders:= ("PEN-G", "aspirin"); +med_allergens := ("penicillin", "aspirin"); +/* Lists three patient allergies and their reactions */ +patient_allergies := ("milk", "codeine", "penicillin"); +patient_reactions := ("hives", NULL, "anaphylaxis"); +/* Passes 4 arguments and receives 3 lists as values */ +(meds, allergens, reactions) := call find_allergies with med_orders, med_allergens, patient_allergies, patient_reactions; + +/* Lists two medications and their allergens */ +med_orders := ("PEN-G", "aspirin"); +med_allergens := ("penicillin", "aspirin"); +/* Lists three patient allergies and their reactions */ +patient_allergies := ("milk", "codeine", "penicillin"); +patient_reactions := ("hives", NULL, "anaphylaxis"); +/* Passes 4 arguments and receives 3 lists as values */ +(meds, allergens, reactions) := call find_allergies with med_orders, med_allergens, patient_allergies, patient_reactions; + +/* Initialize variables */ +a_list:= (); +m_list:= (); +r_list:= (); +num:= 1; +/* Checks each allergen in the medications to determine if the patient is +allergic to it */ +while num <= (count med_allergen) do +allergen:= last(first num from med_allergens); +allergy_found:= (patient_allergies = allergen); +reaction:= patient_reactions where allergy_found; +medication:= med_orders where (med_allergens = allergen); +/* Adds the allergen, medication, and reaction to variables that will */ +/* be returned to the calling MLM */ +If any allergy_found then +a_list:= a_list, allergen; +m_list:= m_list, medication; +r_list:= r_list, reaction; +endif; +/* Increments the counter that is used to stop the while-loop */ +num:= num + 1 ; +enddo; + +num:= 1; +/* Checks each allergen in the medications and stops if patient is allergic +to it */ +while num <= (count med_allergen) do +allergen:= last(first num from med_allergens); +allergy_found:= (patient_allergies = allergen); +/* be returned to the calling MLM */ +If any allergy_found then +breakloop; // execution of the while-loop will stop immediately +endif; +/* Increments the counter that is used to stop the while-loop */ +num:= num + 1 ; +enddo; + +/* Initialize variables */ +a_list:= (); +m_list:= (); +r_list:= (); +/* Checks each allergen in the medications to determine if the patient is +allergic to it */ +for allergen in med_allergens do +allergy_found:= (patient_allergies = allergen); +reaction:= patient_reactions where allergy_found; +medication:= med_orders where (med_allergens = allergen); +/* Adds the allergen, medication, and reaction to variables that will */ +/* be returned to the calling MLM */ +If any allergy_found then +a_list:= a_list, allergen; +m_list:= m_list, medication; +r_list:= r_list, reaction; +endif; +enddo; + +dose := NEW MedicationDose with "Ampicillin", "500mg", "Active"; +dose := NEW MedicationDose with "Ampicillin", ("500", "700"), "Active"; +testobj := NEW obj_def with [z:=10, y:="roger"]; + + +;; +ACTION: + +var := surgery_time WAS BEFORE discharge_time; +var := surgery_time IS NOT AFTER discharge_time; +var := 3 IS WITHIN 2 TO 5; +var := 3 IS WITHIN 5 TO 2; +var := 1990-03-10T00:00:00 IS WITHIN 1990-03-05T00:00:00 TO 1990-03-15T00:00:00; +var := 3 days IS WITHIN 2 days TO 5 months; +var := "ccc" IS WITHIN "a" TO "d"; +var := 1990-03-10T15:00:00 IS WITHIN 16:00:00 TO 17:00:00; + +var := 1990-03-10T15:00:00 IS WITHIN 17:00:00 TO 16:00:00; +var := time of day of time of order IS WITHIN 22:00:00 to 02:00:00; +var := DAY OF WEEK OF TIME OF measurement IS WITHIN MONDAY TO FRIDAY; +var := measurement OCCURRED WITHIN MONDAY to FRIDAY; +var := WEDNESDAY IS WITHIN TUESDAY TO FRIDAY; +var := SATURDAY IS WITHIN FRIDAY TO SUNDAY; +var := SATURDAY IS WITHIN FRIDAY TO MONDAY; + +var := 1990-03-08T00:00:00 IS WITHIN 3 days PRECEDING 1990-03-10T00:00:00; +var := 1990-03-08T00:00:00 IS WITHIN 3 days FOLLOWING 1990-03-10T00:00:00; +var := 1990-03-08T00:00:00 IS WITHIN 3 days SURROUNDING 1990-03-10T00:00:00; +var := time of day of time of request is within 2 hours surrounding 14:00; +var := time of day of time of measurements are within 30 minutes surrounding 13:00; +var := 1990-03-08T00:00:00 IS WITHIN PAST 3 days; +var := 12:00:00 IS WITHIN PAST 2 weeks; +var := 1990-03-08T11:11:11 IS WITHIN SAME DAY AS 1990-03-08T01:01:01; +var := 12:00:00 IS WITHIN SAME DAY AS 1990-03-08T01:01:01; +var := 1990-03-08T00:00:00 IS BEFORE 1990-03-07T00:00:00; +var := 1990-03-08T00:00:00 IS BEFORE 1990-03-08T00:00:00; +var := 1990-03-08T00:00:00 IS AFTER 1990-03-07T00:00:00; +var := now is after 18:00:00; +var := 2 IS IN (4, 5, 6); +var := (3, 4) IS IN (4, 5, 6); +var := null is in (1/0, 2); +var := day of week of (time of potassium) IS IN (SATURDAY, SUNDAY); + +var := 3 IS PRESENT; +var := null IS PRESENT; +var := (3, null) IS PRESENT; +var := (3, null) IS NULL; +var := false IS BOOLEAN; +var := 3 IS NOT BOOLEAN; +var := (null, false,3) IS BOOLEAN; +var := TRUTH VALUE .44 IS TRUTH VALUE; +var := 3 IS NOT TRUTH VALUE; +var := (null, TRUTH VALUE .44, 3) IS TRUTH VALUE; +var := RangeOfAge IS LINGUISTIC VARIABLE; +var := 3 IS NOT LINGUISTIC VARIABLE; +var := (null, RangeOfAge,3) IS LINGUISTIC VARIABLE; +var := 3 IS NUMBER; +var := null IS NUMBER; +var := sum(serum_K where it IS NUMBER); +var := "asdf" IS STRING; +var := null IS STRING; +var := 1991-03-12T00:00:00 IS TIME; +var := null IS TIME; +var := 23:20:00 IS TIME OF DAY; +var := 23:20:00.12 IS TIME OF DAY; +var := 1991-03-12T00:00:00 IS TIME OF DAY; +var := null IS TIME OF DAY; +var := (3 days) IS DURATION; +var := null IS DURATION; +var := (3, 2, 1) IS LIST; +var := 5 IS LIST; +var := null IS LIST; +var := (3, 2, "asdf") IS LIST; +var := (3, 2, "asdf") IS NUMBER; +var := 2 IN (4, 5, 6); +var := (3, 4) IN (4, 5, 6); +var := null in (1/0, 2); +var := 3 IS FUZZY; +var := (FUZZY SET (0, truth value 0), (1, truth value 1)) IS FUZZY; +var := (today fuzzified by 2 days) IS FUZZY; +var := 3 IS CRISP; +var := (FUZZY SET (0, truth value 0), (1, truth value 1)) IS CRISP; +var := (today fuzzified by 2 days) IS CRISP; + +var := 4 + 2; +var := 5 + (); +var := (1,2,3) + (); +var := null + (); +var := 5 + null; +var := (1, 2, 3) + null; +var := null + null; +var := 1 day + 2 days; +var := 1990-03-13T00:00:00 + 2 days; +var := 0000-00-00 + 1993 years + 5 months + 17 days; +var := 2 days + 1990-03-13T00:00:00; + +var := + 2; +var := + "asdf"; +var := + 2 days; +var := 6 - 2; +var := 3 days - 2 days; +var := 1990-03-15T00:00:00 - 2 days; +var := 1990-03-15T00:00:00 - 1990-03-13T00:00:00; +var := - 2; +var := - (2 days); +var := 4 * 2; +var := 3 * 2 days; +var := 2 days * 3; +var := 8 / 2; +var := 6 days / 3; +var := 2 minutes / 1 second; +var := 3 years / 1 month; +var := 3 ** 2; + +var := SUM a_list; +var := SUM OF a_list; +var := SUM(a_list); +var := SUM OF(a_list); + +var := AVERAGE OF LAST 3 FROM a_list; + +var := COUNT (12, 13, 14, null); +var := COUNT "asdf"; +var := COUNT (); +var := COUNT null; + +var := EXIST (12, 13, 14); +var := EXIST null; +var := EXIST (); +var := EXIST ("plugh", null); + +var := AVERAGE (12, 13, 17); +var := AVERAGE 3; +var := AVERAGE (); +var := AVERAGE (1990-03-10T03:10:00, 1990-03-12T03:10:00); +var := AVERAGE (03:10:00, 1990-03-12T03:10:00); +var := AVERAGE (03:10:00, 05:10:00); +var := AVERAGE (2 days, 3 days, 4 days); + +var := MEDIAN (12, 17, 13); +var := MEDIAN 3; +var := MEDIAN (); +var := MEDIAN (1990-03-10T03:10:00, 1990-03-11T03:10:00, 1990-03-28T03:10:00); +var := MEDIAN (03:10:00, 02:10:00, 23:10:00); +var := MEDIAN (1 hour, 3 days, 4 years); + +var := SUM (12, 13, 14); +var := SUM 3; +var := SUM (); +var := SUM (1 day, 6 days); + +var := STDDEV (12, 13, 14, 15, 16); +var := STDDEV 3; +var := STDDEV (); + +var := VARIANCE (12, 13, 14, 15, 16); +var := VARIANCE 3; +var := VARIANCE (); + +var := MINIMUM (12, 13, 14); +var := MIN 3; +var := MINIMUM (); +var := MINIMUM (1, "abc"); + +var := minimum (0, 30, 90, 180, 200, 300) using cosine of it; + +var := MAXIMUM (12, 13, 14); +var := MAXIMUM 3; +var := MAXIMUM (); +var := MAXIMUM (1,"abc"); + +var := maximum (0, 30, 90, 180, 200, 300) using sine of it; + +var := LAST (12, 13, 14); +var := LAST 3; +var := LAST (); + +var := FIRST (12, 13, 14); +var := FIRST 3; +var := FIRST (); + +var := ANY IsTrue (true, false, false); +var := ANY false; +var := ANY (); +var := ANY (3, 5, "red"); +var := ANY (false, false); +var := ANY (false, null); + +var := ALL AreTrue (true, false, false); +var := ALL false; +var := ALL (); +var := ALL (3, 5, "red"); +var := ALL (true, null); + +var := NO IsTrue (true, false, false); +var := NO false; +var := NO (); +var := NO (3, 5, "red"); +var := NO (false, null); + +var := LATEST (); +var := LATEST ("penicillin", "ibuprofen", "pseudoephedrine HCL"); + +var := EARLIEST (); +var := EARLIEST ("penicillin", "ibuprofen", "pseudoephedrine HCL"); + +var := (10, 20, 30, 40)[2]; +var := (10, 20)[()]; +var := (10, 20)[1.5, 2]; +var := (10, 20, 30, 40, 50)[1, 3, 5]; +var := (10, 20, 30, 40, 50)[1, (3, 5)]; +var := (10, 20, 30, 40, 50)[1 seqto 3]; + +var := EXTRACT CHARACTERS "abc"; +var := EXTRACT CHARACTERS ("ab", "c"); +var := EXTRACT CHARACTERS (); +var := EXTRACT CHARACTERS ""; +var := STRING REVERSE EXTRACT CHARACTERS "abcde"; + +var := 2 SEQTO 4; +var := 4 SEQTO 2; +var := 4.5 SEQTO 2; +var := 2 SEQTO 2; +var := (-3) SEQTO (-1); +var := 2 * (1 SEQTO 4); +var := (1.5 seqto 5); + +var := reverse (1, 2, 3); +var := reverse (1 seqto 6); +var := reverse (); + +var := INDEX LATEST (); +var := INDEX LATEST ("penicillin", "ibuprofen", "pseudophedrine HCL"); + +var := INDEX EARLIEST (); +var := INDEX EARLIEST ("penicillin", "ibuprofen", "pseudophedrine HCL"); + +var := INDEX MINIMUM (12, 13, 14); +var := INDEX MIN 3; +var := INDEX MINIMUM (); +var := INDEX MINIMUM (1, "abc"); + +var := INDEX MAXIMUM (12, 13, 14); +var := INDEX MAX 3; +var := INDEX MAXIMUM (); +var := INDEX MAXIMUM (1, "abc"); + +var := INTERVAL datas; +var := INTERVAL (3, 4); + +var := ARCCOS 1; + +var := ARCSIN 0; + +var := ARCTAN 0; + +var := COSINE 0; + +var := SINE 0; + +var := TANGENT 0; + +var := EXP 0; + +var := LOG 1; + +var := LOG10 10; + +var := INT (-1.5); +var := INT (-2.0); +var := INT (1.5); +var := INT (-2.5); +var := INT (-3.1); +var := INT (-4); + +var := CEILING (-1.5); +var := CEILING (-1.0); +var := CEILING 1.5; +var := CEILING (-2.5); +var := CEILING (-3.9); + +var := TRUNCATE (-1.5); +var := TRUNCATE (-1.0); +var := TRUNCATE 1.5; + +var := ROUND 0.5; +var := ROUND 3.4; +var := ROUND 3.5; +var := ROUND (-3.5); +var := ROUND (-3.4); +var := ROUND (-3.7); + +var := ABS (-1.5); + +var := SQRT 4; +var := SQRT(-1); + +var := "5" AS NUMBER; +var := "xyz" AS NUMBER; +var := True AS NUMBER; +var := False AS NUMBER; +var := 6 AS NUMBER; +var := ("7", 8, "2.3E+2", 4.1E+3, "ABC", Null, True, False, 1997-10-31T00:00:00, now, 3 days) AS NUMBER; +var := () AS NUMBER; + +var := "1999-12-12" AS TIME; +var := "xyz" AS TIME; +var := ("1999-12-12", 1999-12-12, "ABC", Null, True, "1997-10-31T00:00:00", 3 days) AS TIME; +var := () AS TIME; + +var := 5 AS STRING; +var := null AS STRING; +var := True AS STRING; +var := False AS STRING; +var := ("7", 8, 4.1E+3, "ABC", Null, True, False, 1997-10-31T00:00:00, 3 days) AS STRING; +var := () AS STRING; + +var := 0.33 AS TRUTH VALUE; +var := "xyz" AS TRUTH VALUE; +var := 400 AS TRUTH VALUE; +var := True AS TRUTH VALUE; +var := False AS TRUTH VALUE; +var := (0, 1, 4.1E+3, 0.33, Null, True, False, 1997-10-31T00:00:00, 3 days, "ABC") AS TRUTH VALUE; +var := () AS TRUTH VALUE; + +WRITE Var; +Applicability_of_action_slot:= conclude; + +WRITE "the patient's potassium is" || serum_pot; +WRITE "this is an email alert" AT email_dest; +WRITE a_message; + +WRITE "the patient's potassium is " || serum_pot; +WRITE CK0023 || serum_pot; + +RETURN (diagnosis_score, diagnosis_name); +RETURN diagnosis_score, diagnosis_name; + +CALL mlmx DELAY 3 days; + + +;; +URGENCY: someIdentifier ;; +RESOURCES: +DEFAULT: en;; +language: en +'msg': "Caution, the patient has the following allergy to penicillin +documented: "; +'creat': "The patient's calculated creatinine clearance is %f ml/min."; +;; +language: de +'msg': "Vorsicht, zu diesem Patienten wurde die folgende Penicillinallergie +dokumentiert: "; +'creat': "Die berechnete Kreatinin-Clearance des Patienten beträgt %f +ml/min."; +;; +END: \ No newline at end of file diff --git a/arden/examples/Third.mlm b/arden/examples/Third.mlm deleted file mode 100644 index e6aa570c25..0000000000 --- a/arden/examples/Third.mlm +++ /dev/null @@ -1,190 +0,0 @@ -maintenance: -title: Dosing for gentamicin in renal failure;; -mlmname: gentamicin_dosing;; -arden: Version 3;; -version: 1.00;; -institution: Columbia-Presbyterian Medical Center;; -author: George Hripcsak, M.D.;; -specialist: ;; -date: 1991-03-18;; -validation: testing;; -library: -purpose: -Suggest an appropriate gentamicin dose in the setting of renal -insufficiency. (This MLM demonstrates a management suggestion.);; -explanation: -Patients with renal insufficiency require the same loading dose of -gentamicin as those with normal renal function, but they require a -reduced daily dose. The creatinine clearance is calculated by serum -creatinine, age, and weight. If it is less than 30 ml/min, then an -appropriate dose is calculated based on the clearance. If the -ordered dose differs from the calculated dose by more than 20 %, -then an alert is generated.;; -keywords: gentamicin; dosing;; -citations: ;; -knowledge: -type: data-driven;; -data: /* an order for gentamicin evokes this MLM */ -gentamicin_order := event {medication_order where -class = gentamicin}; -/* gentamicin doses */ -(loading_dose, periodic_dose, periodic_interval) := -read last {medication_order initial dose, -periodic dose, interval}; -/* serum creatinine mg/dl */ -serum_creatinine := read last ({serum_creatinine} -where it occurred within the past 1 week); -/* birthdate */ -birthdate := read last {birthdate}; -/* weight kg */ -weight := read last ({weight} -where it occurred within the past 3 months); -;; -evoke: -gentamicin_order;; -logic: age := (now - birthdate) / 1 year; -creatinine_clearance := (140 - age) * (weight) / -(72 * serum_creatinine); -/* the algorithm can be adjusted to handle higher clearances */ -if creatinine_clearance < 30 then -calc_loading_dose := 1.7 * weight; -calc_daily_dose := 3 * (0.05 + creatinine_clearance / 100); -ordered_daily_dose := periodic_dose * -periodic_interval /(1 day); -/* check whether order is appropriate */ -if (abs(loading_dose - calc_loading_dose) / -calc_loading_dose > 0.2) -or (abs(ordered_daily_dose - calc_daily_dose) / -calc_daily_dose > 0.2) then -conclude true; -endif; -endif; -;; -action: write "Due to renal insufficiency, the dose of gentamicin " || -"should be adjusted. The patient's calculated " || -"creatinine clearance is " || creatinine_clearance || -" ml/min. A single loading dose of " || -calc_loading_dose || " mg should be given, followed by " || -calc_daily_dose || " mg daily. Note that dialysis may " || -"necessitate additional loading doses."; -;; -urgency: 50;; -end: - -maintenance: -title: Monitor renal function while taking gentamicin;; -mlmname: gentamicin_monitoring;; -arden: Version 3;; -version: 1.00;; -institution: Columbia-Presbyterian Medical Center;; -author: George Hripcsak, M.D.;; -specialist: ;; -date: 1991-03-19;; -validation: testing;; -library: -purpose: -Monitor the patient's renal function when the patient is taking -gentamicin. (This MLM demonstrates periodic monitoring.);; -explanation: -This MLM runs every five days after the patient is placed on -gentamicin until the medication is stopped. If the serum creatinine -has not been checked recently, then an alert is generated -requesting follow-up. If the serum creatinine has been checked, is -greater than 2.0, and has risen by more than 20 %, then an alert is -generated warning that the patient may be developing renal -insufficiency due to gentamicin.;; -keywords: gentamicin; renal function;; -citations: ;; -knowledge: -type: data-driven;; -data: /* an order for gentamicin evokes this MLM */ -gentamicin_order := event {medication_order where -class = gentamicin}; -/* check whether gentamicin has been discontinued */ -gentamicin_discontinued := -read exist({medication_cancellation where class = gentamicin} -where it occurs after eventtime); -/* baseline serum creatinine mg/dl */ -baseline_creatinine := read last ({serum_creatinine} -where it occurred before eventtime); -/* followup serum creatinine mg/dl */ -recent_creatinine := read last ({serum_creatinine} -where it occurred within the past 3 days); -;; -evoke: every 5 days for 10 years starting 5 days after time of -gentamicin_order until gentamicin_discontinued;; -logic: if recent_creatinine is not present then -no_recent_creatinine := true; -conclude true; -elseno_recent_creatinine := false; -if % increase of (serum_creatinine, -recent_creatinine) > 20 /* % */ -and recent_creatinine > 2.0 then -conclude true; -endif; -endif; -;; -action: if no_recent_creatinine then -write "Suggest obtaining a serum creatinine to follow up " || -"on renal function in the setting of gentamicin."; -else -write "Recent serum creatinine (" || recent_creatinine || -" mg/dl) has increased, possibly due to renal " || -"insufficiency related to gentamicin use."; -endif; -;; -urgency: 50;; -end: - -maintenance: -title: Granulocytopenia and Trimethoprim/Sulfamethoxazole;; -mlmname: anctms;; -arden: Version 3;; -version: 2.00;; -institution: Columbia-Presbyterian Medical Center;; -author: George Hripcsak, M.D.;; -specialist: ;; -date: 1991-05-28;; -validation: testing;; -library: -purpose: -Detect granulocytopenia possibly due to -trimethoprim/sulfamethoxazole;; -explanation: -This MLM detects patients that are currently taking -trimethoprim/sulfamethoxazole whose absolute neutrophile count is -less than 1000 and falling.;; -keywords: -granulocytopenia; agranulocytosis; trimethoprim; sulfamethoxazole;; -citations: -1. refute "Anti-infective drug use in relation to the risk of -agranulocytosis and aplastic anemia. A report from the -International Agranulocytosis and Aplastic Anemia Study. -Archives of Internal Medicine, May 1989, 149(5):1036-40.";; -links: MeSH_link 'Some link term' "Some link string";; -knowledge: -type: data-driven;; -data: /* capitalized text within curly brackets would be replaced with */ -/* an institution's own query */ -let anc_storage be event {STORAGE OF ABSOLUTE_NEUTROPHILE_COUNT}; -let anc be read last 2 from ({ABSOLUTE_NEUTROPHILE_COUNT} -where they occurred within the past 1 week); -let pt_is_taking_tms be read exist -{TRIMETHOPRIM_SULFAMETHOXAZOLE_ORDER}; -;; -evoke: anc_storage;; -logic: if pt_is_taking_tms -and the last anc is less than 1000 -and the last anc is less than the first anc -/* is anc falling? */ -then -conclude true; -else -conclude false; -endif; -;; -action: -write "Caution: patient's relative granulocytopenia may be " || -"exacerbated by trimethoprim/sulfamethoxazole."; -;; -end: \ No newline at end of file diff --git a/arden/pom.xml b/arden/pom.xml index 8d8866ef7c..23e4e6e0df 100644 --- a/arden/pom.xml +++ b/arden/pom.xml @@ -5,16 +5,13 @@ 4.0.0 arden jar - ANTLR Arden Syntax grammar + Arden Syntax grammar org.antlr.grammars grammarsv4 1.0-SNAPSHOT - org.example - mlm - 1.0-SNAPSHOT @@ -23,7 +20,8 @@ ${antlr.version} - ArdenParser.g4 + ArdenParser.g4 + ArdenLexer.g4 true true @@ -44,8 +42,8 @@ false false - mlms - ARDEN + mlm + Arden examples/ diff --git a/pom.xml b/pom.xml index ade6751a3d..9ef0a26827 100644 --- a/pom.xml +++ b/pom.xml @@ -137,6 +137,7 @@ apex apt aql + arden argus arithmetic asl From dbfdb998182e1bd114ad26d731f9825d3424717b Mon Sep 17 00:00:00 2001 From: Christian Weich Date: Thu, 19 Sep 2024 13:22:47 +0200 Subject: [PATCH 2/2] Remove method names --- arden/ArdenParser.g4 | 256 +++++++++++++++++++++---------------------- 1 file changed, 128 insertions(+), 128 deletions(-) diff --git a/arden/ArdenParser.g4 b/arden/ArdenParser.g4 index ec16ab73f6..f600a597f7 100644 --- a/arden/ArdenParser.g4 +++ b/arden/ArdenParser.g4 @@ -152,37 +152,37 @@ languageSlot ; dataStatement - : identifierBecomes (expr | newObjectPhrase | callPhrase | fuzzySetPhrase) # DataIdentifierOrObjectAssign - | (IDENTIFIER ASSIGN | LET IDENTIFIER BE) dataIdentifierAssign # DataIdentifierAssignPhrase - | (LPAREN dataVarList RPAREN ASSIGN | LET LPAREN dataVarList RPAREN BE) (READ (AS IDENTIFIER)? readPhrase | ARGUMENT | callPhrase) # DataDataVarList - | (fhirObject ASSIGN | LET fhirObject BE) READ AS LATEST? fhirObject fhirReadPhrase? # DataFhir - | IF expr THEN (dataStatement SC)* dataElseIf AGGREGATE? # DataIf - | FOR identifierOrObjectRef IN expr DO (dataStatement SC)* ENDDO # DataFor - | WHILE expr DO (dataStatement SC)* ENDDO # DataWhile - | SWITCH identifierOrObjectRef dataSwitchCases ENDSWITCH AGGREGATE? # DataSwitch - | (timeBecomes | applicabilityBecomes) expr # DataTimeOrApplicabilityAssign - | BREAKLOOP # DataBreakLoop - | INCLUDE IDENTIFIER # DataInclude + : identifierBecomes (expr | newObjectPhrase | callPhrase | fuzzySetPhrase) + | (IDENTIFIER ASSIGN | LET IDENTIFIER BE) dataIdentifierAssign + | (LPAREN dataVarList RPAREN ASSIGN | LET LPAREN dataVarList RPAREN BE) (READ (AS IDENTIFIER)? readPhrase | ARGUMENT | callPhrase) + | (fhirObject ASSIGN | LET fhirObject BE) READ AS LATEST? fhirObject fhirReadPhrase? + | IF expr THEN (dataStatement SC)* dataElseIf AGGREGATE? + | FOR identifierOrObjectRef IN expr DO (dataStatement SC)* ENDDO + | WHILE expr DO (dataStatement SC)* ENDDO + | SWITCH identifierOrObjectRef dataSwitchCases ENDSWITCH AGGREGATE? + | (timeBecomes | applicabilityBecomes) expr + | BREAKLOOP + | INCLUDE IDENTIFIER ; dataElseIf - : ENDIF # DataEndIf - | ELSE (dataStatement SC)* ENDIF # DataElse - | ELSEIF expr THEN (dataStatement SC)* dataElseIf # DataElseIfRecursive + : ENDIF + | ELSE (dataStatement SC)* ENDIF + | ELSEIF expr THEN (dataStatement SC)* dataElseIf ; dataSwitchCases - : CASE exprFactor (dataStatement SC)* dataSwitchCases? # DataSwitchCase - | DEFAULT (dataStatement SC)* # DataSwitchDefault + : CASE exprFactor (dataStatement SC)* dataSwitchCases? + | DEFAULT (dataStatement SC)* ; dataIdentifierAssign - : READ (AS IDENTIFIER)? readPhrase # DataRead - | MLM (TERM (FROM INSTITUTION STRING)? | MLM_SELF) # DataMlm - | (INTERFACE | EVENT | MESSAGE | DESTINATION) mappingFactor # DataInterface - | (MESSAGE | DESTINATION) AS IDENTIFIER mappingFactor? # DataMessage - | ARGUMENT # DataArgument - | (OBJECT | LINGUISTIC VARIABLE) objectDefinition # DataObject + : READ (AS IDENTIFIER)? readPhrase + | MLM (TERM (FROM INSTITUTION STRING)? | MLM_SELF) + | (INTERFACE | EVENT | MESSAGE | DESTINATION) mappingFactor + | (MESSAGE | DESTINATION) AS IDENTIFIER mappingFactor? + | ARGUMENT + | (OBJECT | LINGUISTIC VARIABLE) objectDefinition ; identifierBecomes @@ -205,9 +205,9 @@ dataVarList ; identifierOrObjectRef - : IDENTIFIER # IdentifierRefIdentifier - | identifierOrObjectRef LBRACK expr RBRACK # IdentifierRefBrack - | identifierOrObjectRef DOT IDENTIFIER # IdentifierRefObject + : IDENTIFIER + | identifierOrObjectRef LBRACK expr RBRACK + | identifierOrObjectRef DOT IDENTIFIER ; newObjectPhrase @@ -223,8 +223,8 @@ objectInitElement ; fuzzySetPhrase - : FUZZY SET fuzzySetInitElement (COMMA fuzzySetInitElement)* # FuzzySet - | exprNegation FUZZIFIED BY exprNegation # FuzzifiedBy + : FUZZY SET fuzzySetInitElement (COMMA fuzzySetInitElement)* + | exprNegation FUZZIFIED BY exprNegation ; fuzzySetInitElement @@ -232,9 +232,9 @@ fuzzySetInitElement ; readPhrase - : (ofReadFuncOp OF?)? mappingFactor (WHERE exprOr)? # OfReadFuncOpReadWhere - | fromOfFuncOp OF? mappingFactor (WHERE exprOr)? # FromOfFuncOpReadWhere - | fromOfFuncOp exprFactor FROM mappingFactor (WHERE exprOr)? # FromOfFuncOpFromReadWhere + : (ofReadFuncOp OF?)? mappingFactor (WHERE exprOr)? + | fromOfFuncOp OF? mappingFactor (WHERE exprOr)? + | fromOfFuncOp exprFactor FROM mappingFactor (WHERE exprOr)? ; mappingFactor @@ -254,16 +254,16 @@ fhirReadPhrase ; fhirAccessPhrase - : IT (DOT IDENTIFIER)+ fhirCompOp exprFactor # FhirCompOpAccess - | FIND exprFactor IN IT (DOT IDENTIFIER)+ # FhirFindInAccess + : IT (DOT IDENTIFIER)+ fhirCompOp exprFactor + | FIND exprFactor IN IT (DOT IDENTIFIER)+ ; fhirCompOp - : simpleCompOp # FhirCompOpSimple - | NOT? EQUAL # FhirCompOpNot - | LESS THAN (OR EQUAL)? # FhirCompOpLess - | GREATER THAN (OR EQUAL)? # FhirCompOpGreater - | IS (IN | NOT) # FhirCompOpIs + : simpleCompOp + | NOT? EQUAL + | LESS THAN (OR EQUAL)? + | GREATER THAN (OR EQUAL)? + | IS (IN | NOT) ; objectDefinition @@ -271,16 +271,16 @@ objectDefinition ; evokeStatement - : simpleTrigger # EvokeSimple - | delayedEventTrigger # EvokeDelayedEvent - | constantTimeTrigger # EvokeConstantTime - | EVERY evokeDuration FOR evokeDuration STARTING startingDelay (UNTIL expr)? # EvokePeriodicEvent - | EVERY evokeDuration FOR evokeDuration STARTING constantTimeTrigger (UNTIL expr)? # EvokePeriodicConstantTime + : simpleTrigger + | delayedEventTrigger + | constantTimeTrigger + | EVERY evokeDuration FOR evokeDuration STARTING startingDelay (UNTIL expr)? + | EVERY evokeDuration FOR evokeDuration STARTING constantTimeTrigger (UNTIL expr)? ; simpleTrigger - : eventOr # SimpleEventOr - | ANY OF? LPAREN eventList RPAREN # SimpleEventList + : eventOr + | ANY OF? LPAREN eventList RPAREN ; delayedEventTrigger @@ -288,8 +288,8 @@ delayedEventTrigger ; constantTimeTrigger - : evokeTimeOr # ConstantTimeOr - | evokeDuration AFTER evokeTime # ConstantAfter + : evokeTimeOr + | evokeDuration AFTER evokeTime ; eventOr @@ -305,13 +305,13 @@ evokeTimeOr ; evokeTimeExpr - : evokeTime # EvokeExprTime - | evokeDuration # EvokeExprDuration + : evokeTime + | evokeDuration ; evokeTime - : (ISO_DATE_TIME | ISO_DATE) # EvokeIso - | (TODAY | TOMORROW | WEEKDAYLITERAL) ATTIME TIME_OF_DAY # EvokeRelative + : (ISO_DATE_TIME | ISO_DATE) + | (TODAY | TOMORROW | WEEKDAYLITERAL) ATTIME TIME_OF_DAY ; evokeDuration @@ -319,66 +319,66 @@ evokeDuration ; startingDelay - : delayedEventTrigger # StartingDelayed - | TIME OF? IDENTIFIER # StartingEvent + : delayedEventTrigger + | TIME OF? IDENTIFIER ; logicStatement - : (identifierBecomes | timeBecomes | applicabilityBecomes) expr # LogicIdentifierAssignSimple - | identifierBecomes (newObjectPhrase | callPhrase | fuzzySetPhrase) # LogicIdentifierAssignComplex - | (LPAREN dataVarList RPAREN ASSIGN | LET LPAREN dataVarList RPAREN BE) callPhrase # LogicDataVarList - | IF expr THEN (logicStatement SC)* logicElseIf AGGREGATE? # LogicIf - | FOR identifierOrObjectRef IN expr DO (logicStatement SC)* ENDDO # LogicFor - | WHILE expr DO (logicStatement SC)* ENDDO # LogicWhile - | SWITCH identifierOrObjectRef logicSwitchCases ENDSWITCH AGGREGATE? # LogicSwitch - | BREAKLOOP # LogicBreakLoop - | CONCLUDE expr # LogicConclude + : (identifierBecomes | timeBecomes | applicabilityBecomes) expr + | identifierBecomes (newObjectPhrase | callPhrase | fuzzySetPhrase) + | (LPAREN dataVarList RPAREN ASSIGN | LET LPAREN dataVarList RPAREN BE) callPhrase + | IF expr THEN (logicStatement SC)* logicElseIf AGGREGATE? + | FOR identifierOrObjectRef IN expr DO (logicStatement SC)* ENDDO + | WHILE expr DO (logicStatement SC)* ENDDO + | SWITCH identifierOrObjectRef logicSwitchCases ENDSWITCH AGGREGATE? + | BREAKLOOP + | CONCLUDE expr ; logicElseIf - : ENDIF # LogicEndIf - | ELSE (logicStatement SC)* ENDIF # LogicElse - | ELSEIF expr THEN (logicStatement SC)* logicElseIf # LogicElseIfRecursive + : ENDIF + | ELSE (logicStatement SC)* ENDIF + | ELSEIF expr THEN (logicStatement SC)* logicElseIf ; logicSwitchCases - : CASE exprFactor (logicStatement SC)* logicSwitchCases? # LogicSwitchCase - | DEFAULT (logicStatement SC)* # LogicSwitchDefault + : CASE exprFactor (logicStatement SC)* logicSwitchCases? + | DEFAULT (logicStatement SC)* ; actionStatement - : (identifierBecomes | applicabilityBecomes) (expr | CONCLUDE) # ActionIdentifierAssign - | IF expr THEN (actionStatement SC)* actionElseIf AGGREGATE? # ActionIf - | FOR identifierOrObjectRef IN expr DO (actionStatement SC)* ENDDO # ActionFor - | WHILE expr DO (actionStatement SC)* ENDDO # ActionWhile - | SWITCH identifierOrObjectRef actionSwitchCases ENDSWITCH AGGREGATE? # ActionSwitch - | timeBecomes expr # ActionTimeAssign - | identifierBecomes newObjectPhrase # ActionIdentifierAssignObject - | callPhrase (DELAY expr)? # ActionCallPhrase - | WRITE expr (AT IDENTIFIER)? # ActionWrite - | RETURN expr # ActionReturn - | BREAKLOOP # ActionBreakLoop + : (identifierBecomes | applicabilityBecomes) (expr | CONCLUDE) + | IF expr THEN (actionStatement SC)* actionElseIf AGGREGATE? + | FOR identifierOrObjectRef IN expr DO (actionStatement SC)* ENDDO + | WHILE expr DO (actionStatement SC)* ENDDO + | SWITCH identifierOrObjectRef actionSwitchCases ENDSWITCH AGGREGATE? + | timeBecomes expr + | identifierBecomes newObjectPhrase + | callPhrase (DELAY expr)? + | WRITE expr (AT IDENTIFIER)? + | RETURN expr + | BREAKLOOP ; actionElseIf - : ENDIF # ActionEndIf - | ELSE (actionStatement SC)* ENDIF # ActionElse - | ELSEIF expr THEN (actionStatement SC)* actionElseIf # ActionElseIfRecursive + : ENDIF + | ELSE (actionStatement SC)* ENDIF + | ELSEIF expr THEN (actionStatement SC)* actionElseIf ; actionSwitchCases - : CASE exprFactor (actionStatement SC)* actionSwitchCases? # ActionSwitchCase - | DEFAULT (actionStatement SC)* # ActionSwitchDefault + : CASE exprFactor (actionStatement SC)* actionSwitchCases? + | DEFAULT (actionStatement SC)* ; expr - : COMMA? exprMerge # ListUnary - | expr COMMA exprMerge # ListBinary + : COMMA? exprMerge + | expr COMMA exprMerge ; exprMerge - : exprSort # ToExprSort - | exprMerge MERGE exprSort # MergeBinary + : exprSort + | exprMerge MERGE exprSort ; exprSort @@ -398,13 +398,13 @@ exprWhere ; exprOr - : exprAnd # ToAnd - | exprOr OR exprAnd # OrBinary + : exprAnd + | exprOr OR exprAnd ; exprAnd - : exprRange # ToRange - | exprAnd AND exprRange # AndBinary + : exprRange + | exprAnd AND exprRange ; exprRange @@ -416,20 +416,20 @@ exprNot ; exprComparison - : exprString (simpleCompOp exprString)? # SimpleComparisonBinary - | FIND exprString IN? STRINGOP exprComparison (STARTING AT exprString)? # FindInStringTernary - | exprString IS NOT? mainCompOp # ComparisonIsMainCompOp - | exprString NOT? IN exprString # InBinary - | exprString OCCUR NOT? (binaryCompOpOccur exprString | ternaryCompOp | AT exprString) # ComparisonOccur - | exprString MATCHES PATTERN exprString # MatchesPatternBinary + : exprString (simpleCompOp exprString)? + | FIND exprString IN? STRINGOP exprComparison (STARTING AT exprString)? + | exprString IS NOT? mainCompOp + | exprString NOT? IN exprString + | exprString OCCUR NOT? (binaryCompOpOccur exprString | ternaryCompOp | AT exprString) + | exprString MATCHES PATTERN exprString ; exprString - : exprPlus # ToExprPlus - | exprString (DOR | FORMATTED WITH) exprPlus # DorFormattedWithBinary - | TRIM (LEFT | RIGHT)? exprString # TrimUnary - | (UPPERCASE | LOWERCASE) exprString # StringCaseUnary - | SUBSTRING exprPlus CHARACTERS (STARTING AT exprPlus)? FROM exprString # SubstringCharactersTernary + : exprPlus + | exprString (DOR | FORMATTED WITH) exprPlus + | TRIM (LEFT | RIGHT)? exprString + | (UPPERCASE | LOWERCASE) exprString + | SUBSTRING exprPlus CHARACTERS (STARTING AT exprPlus)? FROM exprString ; exprPlus @@ -449,8 +449,8 @@ exprAtTime ; exprBefore - : exprAgo # ToExprAgo - | exprAgo (BEFORE | AFTER | FROM) exprAgo # BeforeAfterFrom + : exprAgo + | exprAgo (BEFORE | AFTER | FROM) exprAgo ; exprAgo @@ -458,19 +458,19 @@ exprAgo ; exprFunction - : exprNegation (AS (NUMBEROP | TIME | STRINGOP | TRUTHVALUE))? # AsUnary - | (ofReadFuncOp | ofNoReadFuncOp) OF? exprFunction # FuncOpsUnary - | fromOfFuncOp OF? exprFunction (USING exprFunction)? # FromOfFuncOpUnary - | REPLACE timePart OF? exprNegation WITH exprFunction # ReplaceWithBinary - | fromOfFuncOp exprNegation FROM exprFunction (USING exprFunction)? # FromOfFuncOpBinary - | NEAREST exprNegation FROM exprFunction # NearestFromBinary - | INDEX indexFromOfFuncOp OF? exprFunction # IndexUnary - | INDEX (MINIMUM | MAXIMUM) OF? exprNegation FROM exprFunction # IndexFromMinMax - | AT (LEAST | MOST) exprNegation OF? ((ISTRUE | ARETRUE)? FROM)? exprFunction # AtLeastMostBinary - | INDEX OF? exprNegation FROM exprFunction # IndexFromBinary - | INDEX NEAREST exprNegation FROM exprFunction # IndexNearestBinary - | ATTRIBUTE exprNegation FROM exprFunction # AttributeFromBinary - | SUBLIST exprNegation ELEMENTS (STARTING AT exprNegation)? FROM exprFunction # SublistTernary + : exprNegation (AS (NUMBEROP | TIME | STRINGOP | TRUTHVALUE))? + | (ofReadFuncOp | ofNoReadFuncOp) OF? exprFunction + | fromOfFuncOp OF? exprFunction (USING exprFunction)? + | REPLACE timePart OF? exprNegation WITH exprFunction + | fromOfFuncOp exprNegation FROM exprFunction (USING exprFunction)? + | NEAREST exprNegation FROM exprFunction + | INDEX indexFromOfFuncOp OF? exprFunction + | INDEX (MINIMUM | MAXIMUM) OF? exprNegation FROM exprFunction + | AT (LEAST | MOST) exprNegation OF? ((ISTRUE | ARETRUE)? FROM)? exprFunction + | INDEX OF? exprNegation FROM exprFunction + | INDEX NEAREST exprNegation FROM exprFunction + | ATTRIBUTE exprNegation FROM exprFunction + | SUBLIST exprNegation ELEMENTS (STARTING AT exprNegation)? FROM exprFunction ; exprNegation @@ -482,17 +482,17 @@ exprDuration ; exprFactor - : exprAtom # ToAtom - | exprFactor LBRACK expr RBRACK # FactorBrack - | exprFactor DOT IDENTIFIER # FactorDot + : exprAtom + | exprFactor LBRACK expr RBRACK + | exprFactor DOT IDENTIFIER ; exprAtom - : (IDENTIFIER | NUMBER | NULL | IT) # AtomMisc - | (STRING | (LOCALIZED TERM (BY exprAtom)?)) # AtomString - | (NOW | ISO_DATE_TIME | ISO_DATE | EVENTTIME | TRIGGERTIME | CURRENTTIME | TIME_OF_DAY | TODAY | TOMORROW | WEEKDAYLITERAL) # AtomTime - | ((TRUTHVALUE? (TRUE | FALSE)) | TRUTHVALUE NUMBER) # AtomBoolean - | LPAREN (expr | fuzzySetPhrase)? RPAREN # AtomRecursive + : (IDENTIFIER | NUMBER | NULL | IT) + | (STRING | (LOCALIZED TERM (BY exprAtom)?)) + | (NOW | ISO_DATE_TIME | ISO_DATE | EVENTTIME | TRIGGERTIME | CURRENTTIME | TIME_OF_DAY | TODAY | TOMORROW | WEEKDAYLITERAL) + | ((TRUTHVALUE? (TRUE | FALSE)) | TRUTHVALUE NUMBER) + | LPAREN (expr | fuzzySetPhrase)? RPAREN ; simpleCompOp @@ -500,10 +500,10 @@ simpleCompOp ; mainCompOp - : unaryCompOp # ToUnaryCompOp - | binaryCompOp exprString # ToBinaryCompOp - | binaryCompOpOccur exprString # ToBinaryCompOpOccur - | ternaryCompOp # ToTernaryCompOp + : unaryCompOp + | binaryCompOp exprString + | binaryCompOpOccur exprString + | ternaryCompOp ; unaryCompOp