| summaryrefslogtreecommitdiff |
diff options
| author | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2021-01-02 23:45:03 +0100 |
|---|---|---|
| committer | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2021-01-02 23:45:03 +0100 |
| commit | 11daf8c58b8a0dd4f4c9babe2660d3779a04465a (patch) | |
| tree | 21955f6c0bd2447079ecf40f181444b73bea633c | |
| parent | e0227a5ea20aaa6eccd260de33235a307cbd85ea (diff) | |
Adds 'for' in 'choice' constructs.
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 |


