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 "\n"
|
||||||
print arr1 << arr2
|
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() {
|
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();
|
final Statement initialization = assignmentStatement();
|
||||||
consume(TokenType.COMMA);
|
consume(TokenType.COMMA);
|
||||||
final Expression termination = expression();
|
final Expression termination = expression();
|
||||||
consume(TokenType.COMMA);
|
consume(TokenType.COMMA);
|
||||||
final Statement increment = assignmentStatement();
|
final Statement increment = assignmentStatement();
|
||||||
match(TokenType.RPAREN); // необязательные скобки
|
if (openParen) consume(TokenType.RPAREN); // скобки
|
||||||
final Statement statement = statementOrBlock();
|
final Statement statement = statementOrBlock();
|
||||||
return new ForStatement(initialization, termination, increment, statement);
|
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() {
|
private FunctionDefineStatement functionDefine() {
|
||||||
final String name = consume(TokenType.WORD).getText();
|
final String name = consume(TokenType.WORD).getText();
|
||||||
consume(TokenType.LPAREN);
|
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(ContinueStatement s);
|
||||||
void visit(DoWhileStatement s);
|
void visit(DoWhileStatement s);
|
||||||
void visit(ForStatement s);
|
void visit(ForStatement s);
|
||||||
|
void visit(ForeachArrayStatement s);
|
||||||
|
void visit(ForeachMapStatement s);
|
||||||
void visit(FunctionDefineStatement s);
|
void visit(FunctionDefineStatement s);
|
||||||
void visit(FunctionReferenceExpression e);
|
void visit(FunctionReferenceExpression e);
|
||||||
void visit(FunctionStatement s);
|
void visit(FunctionStatement s);
|
||||||
|
@ -75,6 +75,18 @@ public abstract class AbstractVisitor implements Visitor {
|
|||||||
s.increment.accept(this);
|
s.increment.accept(this);
|
||||||
s.statement.accept(this);
|
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
|
@Override
|
||||||
public void visit(FunctionDefineStatement s) {
|
public void visit(FunctionDefineStatement s) {
|
||||||
|
Loading…
Reference in New Issue
Block a user