Skip to content

Commit a3b6cd2

Browse files
OlgaNovgantonmedv
andauthored
Add if-else conditional (#736)
Co-authored-by: Anton Medvedev <[email protected]>
1 parent 6ef04ec commit a3b6cd2

File tree

6 files changed

+86
-4
lines changed

6 files changed

+86
-4
lines changed

docs/language-definition.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ Backticks strings are raw strings, they do not support escape sequences.
9797
<tr>
9898
<td><strong>Conditional</strong></td>
9999
<td>
100-
<code>?:</code> (ternary), <code>??</code> (nil coalescing)
100+
<code>?:</code> (ternary), <code>??</code> (nil coalescing), <code>if {} else {}</code> (multiline)
101101
</td>
102102
</tr>
103103
<tr>

expr_test.go

+15
Original file line numberDiff line numberDiff line change
@@ -1291,6 +1291,21 @@ func TestExpr(t *testing.T) {
12911291
`1 < 2 < 3 == true`,
12921292
true,
12931293
},
1294+
{
1295+
`if 1 > 2 { 333 * 2 + 1 } else { 444 }`,
1296+
444,
1297+
},
1298+
{
1299+
`let a = 3;
1300+
let b = 2;
1301+
if a>b {let c = Add(a, b); c+1} else {Add(10, b)}
1302+
`,
1303+
6,
1304+
},
1305+
{
1306+
`if "a" < "b" {let x = "a"; x} else {"abc"}`,
1307+
"a",
1308+
},
12941309
}
12951310

12961311
for _, tt := range tests {

parser/lexer/lexer_test.go

+36
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,42 @@ func TestLex(t *testing.T) {
239239
{Kind: EOF},
240240
},
241241
},
242+
{
243+
`if a>b {x1+x2} else {x2}`,
244+
[]Token{
245+
{Kind: Operator, Value: "if"},
246+
{Kind: Identifier, Value: "a"},
247+
{Kind: Operator, Value: ">"},
248+
{Kind: Identifier, Value: "b"},
249+
{Kind: Bracket, Value: "{"},
250+
{Kind: Identifier, Value: "x1"},
251+
{Kind: Operator, Value: "+"},
252+
{Kind: Identifier, Value: "x2"},
253+
{Kind: Bracket, Value: "}"},
254+
{Kind: Operator, Value: "else"},
255+
{Kind: Bracket, Value: "{"},
256+
{Kind: Identifier, Value: "x2"},
257+
{Kind: Bracket, Value: "}"},
258+
{Kind: EOF},
259+
},
260+
},
261+
{
262+
`a>b if {x1} else {x2}`,
263+
[]Token{
264+
{Kind: Identifier, Value: "a"},
265+
{Kind: Operator, Value: ">"},
266+
{Kind: Identifier, Value: "b"},
267+
{Kind: Operator, Value: "if"},
268+
{Kind: Bracket, Value: "{"},
269+
{Kind: Identifier, Value: "x1"},
270+
{Kind: Bracket, Value: "}"},
271+
{Kind: Operator, Value: "else"},
272+
{Kind: Bracket, Value: "{"},
273+
{Kind: Identifier, Value: "x2"},
274+
{Kind: Bracket, Value: "}"},
275+
{Kind: EOF},
276+
},
277+
},
242278
}
243279

244280
for _, test := range tests {

parser/lexer/state.go

+1-3
Original file line numberDiff line numberDiff line change
@@ -129,9 +129,7 @@ loop:
129129
switch l.word() {
130130
case "not":
131131
return not
132-
case "in", "or", "and", "matches", "contains", "startsWith", "endsWith":
133-
l.emit(Operator)
134-
case "let":
132+
case "in", "or", "and", "matches", "contains", "startsWith", "endsWith", "let", "if", "else":
135133
l.emit(Operator)
136134
default:
137135
l.emit(Identifier)

parser/parser.go

+22
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ func (p *parser) parseExpression(precedence int) Node {
132132
if precedence == 0 && p.current.Is(Operator, "let") {
133133
return p.parseVariableDeclaration()
134134
}
135+
if p.current.Is(Operator, "if") {
136+
return p.parseConditionalIf()
137+
}
135138

136139
nodeLeft := p.parsePrimary()
137140

@@ -235,6 +238,25 @@ func (p *parser) parseVariableDeclaration() Node {
235238
return let
236239
}
237240

241+
func (p *parser) parseConditionalIf() Node {
242+
p.next()
243+
nodeCondition := p.parseExpression(0)
244+
p.expect(Bracket, "{")
245+
expr1 := p.parseExpression(0)
246+
p.expect(Bracket, "}")
247+
p.expect(Operator, "else")
248+
p.expect(Bracket, "{")
249+
expr2 := p.parseExpression(0)
250+
p.expect(Bracket, "}")
251+
252+
return &ConditionalNode{
253+
Cond: nodeCondition,
254+
Exp1: expr1,
255+
Exp2: expr2,
256+
}
257+
258+
}
259+
238260
func (p *parser) parseConditional(node Node) Node {
239261
var expr1, expr2 Node
240262
for p.current.Is(Operator, "?") && p.err == nil {

parser/parser_test.go

+11
Original file line numberDiff line numberDiff line change
@@ -647,6 +647,17 @@ world`},
647647
Right: &BoolNode{Value: true},
648648
},
649649
},
650+
{
651+
"if a>b {true} else {x}",
652+
&ConditionalNode{
653+
Cond: &BinaryNode{
654+
Operator: ">",
655+
Left: &IdentifierNode{Value: "a"},
656+
Right: &IdentifierNode{Value: "b"},
657+
},
658+
Exp1: &BoolNode{Value: true},
659+
Exp2: &IdentifierNode{Value: "x"}},
660+
},
650661
}
651662
for _, test := range tests {
652663
t.Run(test.input, func(t *testing.T) {

0 commit comments

Comments
 (0)