From 61d7a84be677a7368ea78dcd0cbea434250a1a09 Mon Sep 17 00:00:00 2001 From: Chris Llanwarne Date: Sun, 26 Mar 2017 09:01:54 -0400 Subject: [PATCH] if then else expressions --- SPEC.md | 20 ++++++++++++++++++++ grammar.hgr | 18 ++++++++++++------ 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/SPEC.md b/SPEC.md index ada4991..eeb53f9 100644 --- a/SPEC.md +++ b/SPEC.md @@ -413,6 +413,7 @@ $expression = $expression '(' ($expression (',' $expression)*)? ')' $expression = '!' $expression $expression = '+' $expression $expression = '-' $expression +$expression = if $expression then $expression else $expression $expression = $expression '*' $expression $expression = $expression '%' $expression $expression = $expression '/' $expression @@ -510,6 +511,25 @@ Below are the valid results for operators on types. Any combination not in the ||`+`|`Int`|`Int`|| ||`!`|`Boolean`|`Boolean`|| +#### If then else + +This is an operator that takes three arguments, a condition expression, an if-true expression and an if-false expression. The condition is always evaluated. If the condition is true then the if-true value is evaluated and returned. If the condition is false, the if-false expression is evaluated and returned. The return type of the if-then-else should be the same, regardless of which side is evaluated or runtime problems might occur. + +Examples: + - Choose whether to say "good morning" or "good afternoon": +``` +Boolean morning = ... +String greeting = "good " + if morning then "morning" else "afternoon" +``` +- Choose how much memory to use for a task: +``` +Int array_length = length(array) +runtime { + memory: if array_length > 100 then "16GB" else "8GB" +} +``` + + ### Operator Precedence Table :pig2: [Cromwell supported](https://github.com/broadinstitute/cromwell#wdl-support) :white_check_mark: diff --git a/grammar.hgr b/grammar.hgr index 6163c49..e04ee8b 100644 --- a/grammar.hgr +++ b/grammar.hgr @@ -25,6 +25,8 @@ grammar { r'output(?!{%_identifier_follow%})' -> output(:output) r'as(?!{%_identifier_follow%})' -> :as r'if(?!{%_identifier_follow%})' -> :if + r'then(?!{%_identifier_follow%})' -> :then + r'else(?!{%_identifier_follow%})' -> :else r'while(?!{%_identifier_follow%})' -> :while r'runtime(?!{%_identifier_follow%})' -> :runtime r'scatter(?!{%_identifier_follow%})' -> :scatter @scatter @@ -101,19 +103,23 @@ grammar { r'\}' -> :rbrace %pop r'\[' -> :lsquare r'\]' -> :rsquare - r'=' -> :equal r'\+' -> :plus r'\*' -> :asterisk r'[0-9]+' -> :integer r'(true|false)(?!{%_identifier_follow%})' -> :boolean + r'if' -> :if + r'else' -> :else + r'then' -> :then r'{%_type%}(?!{%_identifier_follow%})' -> :type r'{%_identifier%}' -> :identifier + # Expression tokens r':' -> :colon r',' -> :comma r'\.' -> :dot r'==' -> :double_equal + r'=' -> :equal r'\|\|' -> :double_pipe r'\&\&' -> :double_ampersand r'!=' -> :not_equal @@ -163,12 +169,8 @@ grammar { } mode { r'\s+' -> null - r'\)' -> :rparen %pop r'\(' -> :lparen - r'\.' -> :dot - r'\[' -> :lsquare - r'\]' -> :rsquare - r'in(?!{%_identifier_follow%})' -> :in + r'in(?!{%_identifier_follow%})' -> :in %pop r'{%_identifier%}' -> :identifier } mode { @@ -202,6 +204,9 @@ grammar { r'\+' -> :plus r'\*' -> :asterisk r'[0-9]+' -> :integer + r'if' -> :if + r'else' -> :else + r'then' -> :then r'{%_identifier%}(?=\s*=)' -> :cmd_attr_hint[] :identifier r'(true|false)(?!{%_identifier_follow%})' -> :boolean r'{%_type%}(?!{%_identifier_follow%})' -> :type @@ -428,6 +433,7 @@ grammar { (*:left) $e = :lsquare list($e, :comma) :rsquare -> ArrayLiteral(values=$1) (*:left) $e = :lbrace list($map_kv, :comma) :rbrace -> MapLiteral(map=$1) (*:left) $e = :lparen list($e, :comma) :rparen -> TupleLiteral(values=$1) + (*:left) $e = :if $e :then $e :else $e -> TernaryIf(cond=$1, iftrue=$3, iffalse=$5) $e = :string $e = :identifier $e = :boolean