mirror of
https://github.com/aNNiMON/Own-Programming-Language-Tutorial.git
synced 2024-09-20 00:34:20 +03:00
Добавлен foreach
This commit is contained in:
parent
fa2295ad18
commit
a17bef18c5
10
program.own
10
program.own
@ -101,3 +101,13 @@ print arr1
|
||||
print "\n"
|
||||
print arr1 << arr2
|
||||
|
||||
for op, func : map {
|
||||
echo (4, op, 5, "=", func(4,5))
|
||||
}
|
||||
|
||||
for v : arr1 print "" + v + ", "
|
||||
print "\n"
|
||||
for (v : arr1 << arr2) print "" + v + ", "
|
||||
print "\n"
|
||||
for v : [1,2,3,4,5,6,7,8,9] print "" + v + ", "
|
||||
|
||||
|
@ -124,17 +124,50 @@ public final class Parser {
|
||||
}
|
||||
|
||||
private Statement forStatement() {
|
||||
match(TokenType.LPAREN); // необязательные скобки
|
||||
int foreachIndex = lookMatch(0, TokenType.LPAREN) ? 1 : 0;
|
||||
if (lookMatch(foreachIndex, TokenType.WORD) && lookMatch(foreachIndex + 1, TokenType.COLON)) {
|
||||
// for v : arr || for (v : arr)
|
||||
return foreachArrayStatement();
|
||||
}
|
||||
if (lookMatch(foreachIndex, TokenType.WORD) && lookMatch(foreachIndex + 1, TokenType.COMMA)
|
||||
&& lookMatch(foreachIndex + 2, TokenType.WORD) && lookMatch(foreachIndex + 3, TokenType.COLON)) {
|
||||
// for key, value : arr || for (key, value : arr)
|
||||
return foreachMapStatement();
|
||||
}
|
||||
|
||||
boolean openParen = match(TokenType.LPAREN); // необязательные скобки
|
||||
final Statement initialization = assignmentStatement();
|
||||
consume(TokenType.COMMA);
|
||||
final Expression termination = expression();
|
||||
consume(TokenType.COMMA);
|
||||
final Statement increment = assignmentStatement();
|
||||
match(TokenType.RPAREN); // необязательные скобки
|
||||
if (openParen) consume(TokenType.RPAREN); // скобки
|
||||
final Statement statement = statementOrBlock();
|
||||
return new ForStatement(initialization, termination, increment, statement);
|
||||
}
|
||||
|
||||
private ForeachArrayStatement foreachArrayStatement() {
|
||||
boolean openParen = match(TokenType.LPAREN); // необязательные скобки
|
||||
final String variable = consume(TokenType.WORD).getText();
|
||||
consume(TokenType.COLON);
|
||||
final Expression container = expression();
|
||||
if (openParen) consume(TokenType.RPAREN); // скобки
|
||||
final Statement statement = statementOrBlock();
|
||||
return new ForeachArrayStatement(variable, container, statement);
|
||||
}
|
||||
|
||||
private ForeachMapStatement foreachMapStatement() {
|
||||
boolean openParen = match(TokenType.LPAREN); // необязательные скобки
|
||||
final String key = consume(TokenType.WORD).getText();
|
||||
consume(TokenType.COMMA);
|
||||
final String value = consume(TokenType.WORD).getText();
|
||||
consume(TokenType.COLON);
|
||||
final Expression container = expression();
|
||||
if (openParen) consume(TokenType.RPAREN); // скобки
|
||||
final Statement statement = statementOrBlock();
|
||||
return new ForeachMapStatement(key, value, container, statement);
|
||||
}
|
||||
|
||||
private FunctionDefineStatement functionDefine() {
|
||||
final String name = consume(TokenType.WORD).getText();
|
||||
consume(TokenType.LPAREN);
|
||||
|
@ -0,0 +1,51 @@
|
||||
package com.annimon.ownlang.parser.ast;
|
||||
|
||||
import com.annimon.ownlang.lib.Value;
|
||||
import com.annimon.ownlang.lib.Variables;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public final class ForeachArrayStatement implements Statement {
|
||||
|
||||
public final String variable;
|
||||
public final Expression container;
|
||||
public final Statement body;
|
||||
|
||||
public ForeachArrayStatement(String variable, Expression container, Statement body) {
|
||||
this.variable = variable;
|
||||
this.container = container;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final Value previousVariableValue = Variables.isExists(variable) ? Variables.get(variable) : null;
|
||||
final Iterable<Value> iterator = (Iterable<Value>) container.eval();
|
||||
for (Value value : iterator) {
|
||||
Variables.set(variable, value);
|
||||
try {
|
||||
body.execute();
|
||||
} catch (BreakStatement bs) {
|
||||
break;
|
||||
} catch (ContinueStatement cs) {
|
||||
// continue;
|
||||
}
|
||||
}
|
||||
// Восстанавливаем переменную
|
||||
if (previousVariableValue != null) {
|
||||
Variables.set(variable, previousVariableValue);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(Visitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("for %s : %s %s", variable, container, body);
|
||||
}
|
||||
}
|
58
src/com/annimon/ownlang/parser/ast/ForeachMapStatement.java
Normal file
58
src/com/annimon/ownlang/parser/ast/ForeachMapStatement.java
Normal file
@ -0,0 +1,58 @@
|
||||
package com.annimon.ownlang.parser.ast;
|
||||
|
||||
import com.annimon.ownlang.lib.Value;
|
||||
import com.annimon.ownlang.lib.Variables;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author aNNiMON
|
||||
*/
|
||||
public final class ForeachMapStatement implements Statement {
|
||||
|
||||
public final String key, value;
|
||||
public final Expression container;
|
||||
public final Statement body;
|
||||
|
||||
public ForeachMapStatement(String key, String value, Expression container, Statement body) {
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
this.container = container;
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
final Value previousVariableValue1 = Variables.isExists(key) ? Variables.get(key) : null;
|
||||
final Value previousVariableValue2 = Variables.isExists(value) ? Variables.get(value) : null;
|
||||
final Iterable<Map.Entry<Value, Value>> iterator = (Iterable<Map.Entry<Value, Value>>) container.eval();
|
||||
for (Map.Entry<Value, Value> entry : iterator) {
|
||||
Variables.set(key, entry.getKey());
|
||||
Variables.set(value, entry.getValue());
|
||||
try {
|
||||
body.execute();
|
||||
} catch (BreakStatement bs) {
|
||||
break;
|
||||
} catch (ContinueStatement cs) {
|
||||
// continue;
|
||||
}
|
||||
}
|
||||
// Восстанавливаем переменные
|
||||
if (previousVariableValue1 != null) {
|
||||
Variables.set(key, previousVariableValue1);
|
||||
}
|
||||
if (previousVariableValue2 != null) {
|
||||
Variables.set(value, previousVariableValue2);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(Visitor visitor) {
|
||||
visitor.visit(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("for %s, %s : %s %s", key, value, container, body);
|
||||
}
|
||||
}
|
@ -17,6 +17,8 @@ public interface Visitor {
|
||||
void visit(ContinueStatement s);
|
||||
void visit(DoWhileStatement s);
|
||||
void visit(ForStatement s);
|
||||
void visit(ForeachArrayStatement s);
|
||||
void visit(ForeachMapStatement s);
|
||||
void visit(FunctionDefineStatement s);
|
||||
void visit(FunctionReferenceExpression e);
|
||||
void visit(FunctionStatement s);
|
||||
|
@ -76,6 +76,18 @@ public abstract class AbstractVisitor implements Visitor {
|
||||
s.statement.accept(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ForeachArrayStatement s) {
|
||||
s.container.accept(this);
|
||||
s.body.accept(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ForeachMapStatement s) {
|
||||
s.container.accept(this);
|
||||
s.body.accept(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(FunctionDefineStatement s) {
|
||||
s.body.accept(this);
|
||||
|
Loading…
Reference in New Issue
Block a user