summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/tests/player_choices.fate45
-rw-r--r--src/core/src/tonkadur/fate/v1/error/UpdatingIllegalVariableFromChoiceException.java46
-rw-r--r--src/core/src/tonkadur/fate/v1/parser/FateParser.g4223
3 files changed, 299 insertions, 15 deletions
diff --git a/data/tests/player_choices.fate b/data/tests/player_choices.fate
index 16c4250..53cbc08 100644
--- a/data/tests/player_choices.fate
+++ b/data/tests/player_choices.fate
@@ -1,19 +1,38 @@
(fate_version 1)
(global int i)
+(global int index_a)
+(global int index_b)
+(global int index_c)
(player_choice
- (
+ (for
+ (
+ (index_a 0)
+ )
+ (< index_a 10)
+ (
+ (index_a (+ 1 index_a))
+ )
+ (option
+ ( Option at index (var index_a) )
+ You selected option at index (var index_a)
+ )
+ )
+)
+
+(player_choice
+ (option
( Wrong Choice 0 )
(set i 1)
(assert (false) FAILED: Player Choice A)
)
- (
+ (option
( Right Choice )
Took the right choice.
(set i 2)
)
- (
+ (option
( Wrong Choice 1 )
(set i 1)
(assert (false) FAILED: Player Choice B)
@@ -24,18 +43,18 @@
(player_choice
(if (false)
- (
+ (option
( Wrong Choice 0 )
(set i 1)
)
)
(ifelse (false)
- (
+ (option
( Wrong Choice 1 )
(set i 3)
)
(if (true)
- (
+ (option
( Right Choice )
(set i 6)
)
@@ -48,7 +67,7 @@
(global (set int) test_set)
(while (>= (var i) 0)
- (add (var i) test_set)
+ (add! (var i) test_set)
(set i (- (var i) 1))
)
@@ -58,21 +77,21 @@
(player_choice
(if (false)
- (
+ (option
( Wrong Choice -1 )
(set i 1)
)
)
(foreach test_set e
(ifelse (= (var e) 3)
- (
+ (option
( Correct Choice (var e) )
(
Chosen var e: (var e)
(set i 653)
)
)
- (
+ (option
( Wrong Choice (var e) )
(
Chosen var e: (var e)
@@ -82,11 +101,11 @@
)
)
(ifelse (false)
- (
+ (option
( Wrong Choice 1 )
(set i 3)
)
- (
+ (option
( Wrong Choice Other )
(set i 6)
)
@@ -98,7 +117,7 @@
(player_choice
(foreach test_set e
(if (= (rand 0 1) 1)
- (
+ (option
( Choice (var e) )
(
Chosen var e: (var e)
diff --git a/src/core/src/tonkadur/fate/v1/error/UpdatingIllegalVariableFromChoiceException.java b/src/core/src/tonkadur/fate/v1/error/UpdatingIllegalVariableFromChoiceException.java
new file mode 100644
index 0000000..7dca8f2
--- /dev/null
+++ b/src/core/src/tonkadur/fate/v1/error/UpdatingIllegalVariableFromChoiceException.java
@@ -0,0 +1,46 @@
+package tonkadur.fate.v1.error;
+
+import tonkadur.error.ErrorLevel;
+
+import tonkadur.parser.Origin;
+import tonkadur.parser.ParsingError;
+
+public class UpdatingIllegalVariableFromChoiceException extends ParsingError
+{
+ /***************************************************************************/
+ /**** MEMBERS **************************************************************/
+ /***************************************************************************/
+ protected final String var_name;
+
+ /***************************************************************************/
+ /**** PUBLIC ***************************************************************/
+ /***************************************************************************/
+ public UpdatingIllegalVariableFromChoiceException
+ (
+ final Origin origin,
+ final String var_name
+ )
+ {
+ super(ErrorLevel.ERROR, ErrorCategory.INVALID_USE, origin);
+
+ this.var_name = var_name;
+ }
+
+ @Override
+ public String toString ()
+ {
+ final StringBuilder sb = new StringBuilder();
+
+ sb.append(origin.toString());
+ sb.append(" ");
+ sb.append(error_category.toString());
+ sb.append(System.lineSeparator());
+
+ sb.append("Updating a variable that wasn't initialized within the ");
+ sb.append("current choice construct ('");
+ sb.append(var_name);
+ sb.append("').");
+
+ return sb.toString();
+ }
+}
diff --git a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4
index 519a01c..fd0dd14 100644
--- a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4
+++ b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4
@@ -12,8 +12,10 @@ options
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
+ import java.util.Collection;
import java.util.Map;
import java.util.HashMap;
+ import java.util.HashSet;
import tonkadur.Files;
@@ -31,6 +33,7 @@ options
import tonkadur.fate.v1.error.DuplicateLocalVariableException;
import tonkadur.fate.v1.error.IllegalReferenceNameException;
import tonkadur.fate.v1.error.InvalidTypeException;
+ import tonkadur.fate.v1.error.UpdatingIllegalVariableFromChoiceException;
import tonkadur.fate.v1.error.UnknownExtensionContentException;
import tonkadur.fate.v1.lang.*;
@@ -47,6 +50,7 @@ options
Deque<Map<String, Variable>> LOCAL_VARIABLES;
Deque<List<String>> HIERARCHICAL_VARIABLES;
int BREAKABLE_LEVELS;
+ Deque<Collection<String>> CHOICE_LIMITED_VARIABLES;
}
/******************************************************************************/
@@ -72,6 +76,7 @@ fate_file [Context context, Deque<Map<String, Variable>> local_variables, World
BREAKABLE_LEVELS = 0;
HIERARCHICAL_VARIABLES.push(new ArrayList<String>());
+ CHOICE_LIMITED_VARIABLES = new ArrayDeque<Collection<String>>();
}
:
WS* FATE_VERSION_KW WORD WS* R_PAREN WS*
@@ -2045,7 +2050,11 @@ returns [Instruction result]
);
}
- | PLAYER_CHOICE_KW player_choice_list WS* R_PAREN
+ | PLAYER_CHOICE_KW
+ {
+ CHOICE_LIMITED_VARIABLES.push(new HashSet<String>());
+ }
+ player_choice_list WS* R_PAREN
{
$result =
new PlayerChoice
@@ -2057,6 +2066,8 @@ returns [Instruction result]
),
($player_choice_list.result)
);
+
+ CHOICE_LIMITED_VARIABLES.pop();
}
| paragraph
@@ -2374,6 +2385,48 @@ returns [Instruction result]
);
}
+ | FOR_KW
+ l0=L_PAREN
+ choice_for_variable_list WS*
+ R_PAREN WS*
+ non_text_value WS*
+ l1=L_PAREN
+ choice_for_update_variable_list WS*
+ R_PAREN WS*
+ player_choice_list
+ WS* R_PAREN
+ {
+ $result =
+ For.build
+ (
+ CONTEXT.get_origin_at
+ (
+ ($FOR_KW.getLine()),
+ ($FOR_KW.getCharPositionInLine())
+ ),
+ ($non_text_value.result),
+ new InstructionList
+ (
+ CONTEXT.get_origin_at
+ (
+ ($l0.getLine()),
+ ($l0.getCharPositionInLine())
+ ),
+ ($choice_for_variable_list.result)
+ ),
+ ($player_choice_list.result),
+ new InstructionList
+ (
+ CONTEXT.get_origin_at
+ (
+ ($l1.getLine()),
+ ($l1.getCharPositionInLine())
+ ),
+ ($choice_for_update_variable_list.result)
+ )
+ );
+ }
+
| FOR_EACH_KW
non_text_value WS+ new_reference_name
{
@@ -2976,7 +3029,7 @@ returns [List<Cons<Variable, Computation>> result]
WS*
(
(
- L_PAREN WS* new_reference_name WS+
+ L_PAREN WS* new_reference_name
{
var_name = ($new_reference_name.result);
}
@@ -3038,6 +3091,172 @@ catch [final Throwable e]
}
}
+choice_for_update_variable_list
+returns [List<Instruction> result]
+@init
+{
+ Collection<String> allowed_variables;
+ String var_name;
+ Origin origin;
+
+ allowed_variables = CHOICE_LIMITED_VARIABLES.peek();
+ var_name = null;
+ origin = null;
+
+ $result = new ArrayList<Instruction>();
+}
+:
+ (
+ WS*
+ (
+ (
+ L_PAREN WS* new_reference_name
+ {
+ var_name = ($new_reference_name.result);
+ origin =
+ CONTEXT.get_origin_at
+ (
+ ($L_PAREN.getLine()),
+ ($L_PAREN.getCharPositionInLine())
+ );
+ }
+ )
+ |
+ (
+ something_else=.
+ {
+ var_name = ($something_else.text).substring(1).trim();
+ origin =
+ CONTEXT.get_origin_at
+ (
+ ($something_else.getLine()),
+ ($something_else.getCharPositionInLine())
+ );
+ }
+ )
+ )
+ WS+ value WS* R_PAREN
+ {
+ $result.add
+ (
+ SetValue.build
+ (
+ origin,
+ ($value.result),
+ VariableFromWord.generate
+ (
+ WORLD,
+ LOCAL_VARIABLES,
+ origin,
+ var_name
+ )
+ )
+ );
+
+ if (!allowed_variables.contains(var_name))
+ {
+ ErrorManager.handle
+ (
+ new UpdatingIllegalVariableFromChoiceException(origin, var_name)
+ );
+ }
+ }
+ )*
+ {
+ }
+;
+catch [final Throwable e]
+{
+ if ((e.getMessage() == null) || !e.getMessage().startsWith("Require"))
+ {
+ throw new ParseCancellationException(CONTEXT.toString() + ((e.getMessage() == null) ? "" : e.getMessage()), e);
+ }
+ else
+ {
+ throw new ParseCancellationException(e);
+ }
+}
+
+choice_for_variable_list
+returns [List<Instruction> result]
+@init
+{
+ Collection<String> allowed_variables;
+ String var_name;
+ Origin origin;
+
+ allowed_variables = CHOICE_LIMITED_VARIABLES.peek();
+ var_name = null;
+ origin = null;
+
+ $result = new ArrayList<Instruction>();
+}
+:
+ (
+ WS*
+ (
+ (
+ L_PAREN WS* new_reference_name
+ {
+ var_name = ($new_reference_name.result);
+ origin =
+ CONTEXT.get_origin_at
+ (
+ ($L_PAREN.getLine()),
+ ($L_PAREN.getCharPositionInLine())
+ );
+ }
+ )
+ |
+ (
+ something_else=.
+ {
+ var_name = ($something_else.text).substring(1).trim();
+ origin =
+ CONTEXT.get_origin_at
+ (
+ ($something_else.getLine()),
+ ($something_else.getCharPositionInLine())
+ );
+ }
+ )
+ )
+ WS+ value WS* R_PAREN
+ {
+ $result.add
+ (
+ SetValue.build
+ (
+ origin,
+ ($value.result),
+ VariableFromWord.generate
+ (
+ WORLD,
+ LOCAL_VARIABLES,
+ origin,
+ var_name
+ )
+ )
+ );
+
+ allowed_variables.add(var_name);
+ }
+ )*
+ {
+ }
+;
+catch [final Throwable e]
+{
+ if ((e.getMessage() == null) || !e.getMessage().startsWith("Require"))
+ {
+ throw new ParseCancellationException(CONTEXT.toString() + ((e.getMessage() == null) ? "" : e.getMessage()), e);
+ }
+ else
+ {
+ throw new ParseCancellationException(e);
+ }
+}
+
variable_list
returns [VariableList result]
@init