Skip to content

Commit a17bef1

Browse files
committed
Добавлен foreach
1 parent fa2295a commit a17bef1

File tree

6 files changed

+168
-2
lines changed

6 files changed

+168
-2
lines changed

program.own

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,3 +101,13 @@ print arr1
101101
print "\n"
102102
print arr1 << arr2
103103

104+
for op, func : map {
105+
echo (4, op, 5, "=", func(4,5))
106+
}
107+
108+
for v : arr1 print "" + v + ", "
109+
print "\n"
110+
for (v : arr1 << arr2) print "" + v + ", "
111+
print "\n"
112+
for v : [1,2,3,4,5,6,7,8,9] print "" + v + ", "
113+

src/com/annimon/ownlang/parser/Parser.java

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -124,17 +124,50 @@ private Statement doWhileStatement() {
124124
}
125125

126126
private Statement forStatement() {
127-
match(TokenType.LPAREN); // необязательные скобки
127+
int foreachIndex = lookMatch(0, TokenType.LPAREN) ? 1 : 0;
128+
if (lookMatch(foreachIndex, TokenType.WORD) && lookMatch(foreachIndex + 1, TokenType.COLON)) {
129+
// for v : arr || for (v : arr)
130+
return foreachArrayStatement();
131+
}
132+
if (lookMatch(foreachIndex, TokenType.WORD) && lookMatch(foreachIndex + 1, TokenType.COMMA)
133+
&& lookMatch(foreachIndex + 2, TokenType.WORD) && lookMatch(foreachIndex + 3, TokenType.COLON)) {
134+
// for key, value : arr || for (key, value : arr)
135+
return foreachMapStatement();
136+
}
137+
138+
boolean openParen = match(TokenType.LPAREN); // необязательные скобки
128139
final Statement initialization = assignmentStatement();
129140
consume(TokenType.COMMA);
130141
final Expression termination = expression();
131142
consume(TokenType.COMMA);
132143
final Statement increment = assignmentStatement();
133-
match(TokenType.RPAREN); // необязательные скобки
144+
if (openParen) consume(TokenType.RPAREN); // скобки
134145
final Statement statement = statementOrBlock();
135146
return new ForStatement(initialization, termination, increment, statement);
136147
}
137148

149+
private ForeachArrayStatement foreachArrayStatement() {
150+
boolean openParen = match(TokenType.LPAREN); // необязательные скобки
151+
final String variable = consume(TokenType.WORD).getText();
152+
consume(TokenType.COLON);
153+
final Expression container = expression();
154+
if (openParen) consume(TokenType.RPAREN); // скобки
155+
final Statement statement = statementOrBlock();
156+
return new ForeachArrayStatement(variable, container, statement);
157+
}
158+
159+
private ForeachMapStatement foreachMapStatement() {
160+
boolean openParen = match(TokenType.LPAREN); // необязательные скобки
161+
final String key = consume(TokenType.WORD).getText();
162+
consume(TokenType.COMMA);
163+
final String value = consume(TokenType.WORD).getText();
164+
consume(TokenType.COLON);
165+
final Expression container = expression();
166+
if (openParen) consume(TokenType.RPAREN); // скобки
167+
final Statement statement = statementOrBlock();
168+
return new ForeachMapStatement(key, value, container, statement);
169+
}
170+
138171
private FunctionDefineStatement functionDefine() {
139172
final String name = consume(TokenType.WORD).getText();
140173
consume(TokenType.LPAREN);
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.annimon.ownlang.parser.ast;
2+
3+
import com.annimon.ownlang.lib.Value;
4+
import com.annimon.ownlang.lib.Variables;
5+
6+
/**
7+
*
8+
* @author aNNiMON
9+
*/
10+
public final class ForeachArrayStatement implements Statement {
11+
12+
public final String variable;
13+
public final Expression container;
14+
public final Statement body;
15+
16+
public ForeachArrayStatement(String variable, Expression container, Statement body) {
17+
this.variable = variable;
18+
this.container = container;
19+
this.body = body;
20+
}
21+
22+
@Override
23+
public void execute() {
24+
final Value previousVariableValue = Variables.isExists(variable) ? Variables.get(variable) : null;
25+
final Iterable<Value> iterator = (Iterable<Value>) container.eval();
26+
for (Value value : iterator) {
27+
Variables.set(variable, value);
28+
try {
29+
body.execute();
30+
} catch (BreakStatement bs) {
31+
break;
32+
} catch (ContinueStatement cs) {
33+
// continue;
34+
}
35+
}
36+
// Восстанавливаем переменную
37+
if (previousVariableValue != null) {
38+
Variables.set(variable, previousVariableValue);
39+
}
40+
}
41+
42+
@Override
43+
public void accept(Visitor visitor) {
44+
visitor.visit(this);
45+
}
46+
47+
@Override
48+
public String toString() {
49+
return String.format("for %s : %s %s", variable, container, body);
50+
}
51+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.annimon.ownlang.parser.ast;
2+
3+
import com.annimon.ownlang.lib.Value;
4+
import com.annimon.ownlang.lib.Variables;
5+
import java.util.Map;
6+
7+
/**
8+
*
9+
* @author aNNiMON
10+
*/
11+
public final class ForeachMapStatement implements Statement {
12+
13+
public final String key, value;
14+
public final Expression container;
15+
public final Statement body;
16+
17+
public ForeachMapStatement(String key, String value, Expression container, Statement body) {
18+
this.key = key;
19+
this.value = value;
20+
this.container = container;
21+
this.body = body;
22+
}
23+
24+
@Override
25+
public void execute() {
26+
final Value previousVariableValue1 = Variables.isExists(key) ? Variables.get(key) : null;
27+
final Value previousVariableValue2 = Variables.isExists(value) ? Variables.get(value) : null;
28+
final Iterable<Map.Entry<Value, Value>> iterator = (Iterable<Map.Entry<Value, Value>>) container.eval();
29+
for (Map.Entry<Value, Value> entry : iterator) {
30+
Variables.set(key, entry.getKey());
31+
Variables.set(value, entry.getValue());
32+
try {
33+
body.execute();
34+
} catch (BreakStatement bs) {
35+
break;
36+
} catch (ContinueStatement cs) {
37+
// continue;
38+
}
39+
}
40+
// Восстанавливаем переменные
41+
if (previousVariableValue1 != null) {
42+
Variables.set(key, previousVariableValue1);
43+
}
44+
if (previousVariableValue2 != null) {
45+
Variables.set(value, previousVariableValue2);
46+
}
47+
}
48+
49+
@Override
50+
public void accept(Visitor visitor) {
51+
visitor.visit(this);
52+
}
53+
54+
@Override
55+
public String toString() {
56+
return String.format("for %s, %s : %s %s", key, value, container, body);
57+
}
58+
}

src/com/annimon/ownlang/parser/ast/Visitor.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ public interface Visitor {
1717
void visit(ContinueStatement s);
1818
void visit(DoWhileStatement s);
1919
void visit(ForStatement s);
20+
void visit(ForeachArrayStatement s);
21+
void visit(ForeachMapStatement s);
2022
void visit(FunctionDefineStatement s);
2123
void visit(FunctionReferenceExpression e);
2224
void visit(FunctionStatement s);

src/com/annimon/ownlang/parser/visitors/AbstractVisitor.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,18 @@ public void visit(ForStatement s) {
7575
s.increment.accept(this);
7676
s.statement.accept(this);
7777
}
78+
79+
@Override
80+
public void visit(ForeachArrayStatement s) {
81+
s.container.accept(this);
82+
s.body.accept(this);
83+
}
84+
85+
@Override
86+
public void visit(ForeachMapStatement s) {
87+
s.container.accept(this);
88+
s.body.accept(this);
89+
}
7890

7991
@Override
8092
public void visit(FunctionDefineStatement s) {

0 commit comments

Comments
 (0)