From fbe5a405d5f8f9be0794a2ff4ac96125869793fe Mon Sep 17 00:00:00 2001 From: Nathanael Sensfelder Date: Tue, 15 Jun 2021 22:57:38 +0200 Subject: ... --- .../fate/v1/lang/computation/Paragraph.java | 9 +- .../fate/v1/lang/meta/VariableFromWord.java | 4 +- .../src/tonkadur/fate/v1/lang/type/ExtraType.java | 43 ++- src/core/src/tonkadur/fate/v1/parser/FateParser.g4 | 92 +++--- src/core/src/tonkadur/fate/v1/parser/Parser.java | 312 -------------------- .../src/tonkadur/fate/v1/parser/ParserData.java | 315 +++++++++++++++++++++ 6 files changed, 408 insertions(+), 367 deletions(-) delete mode 100644 src/core/src/tonkadur/fate/v1/parser/Parser.java create mode 100644 src/core/src/tonkadur/fate/v1/parser/ParserData.java diff --git a/src/core/src/tonkadur/fate/v1/lang/computation/Paragraph.java b/src/core/src/tonkadur/fate/v1/lang/computation/Paragraph.java index 26b08b4..f2959b2 100644 --- a/src/core/src/tonkadur/fate/v1/lang/computation/Paragraph.java +++ b/src/core/src/tonkadur/fate/v1/lang/computation/Paragraph.java @@ -5,6 +5,7 @@ import java.util.List; import tonkadur.parser.Origin; import tonkadur.fate.v1.lang.meta.ComputationVisitor; +import tonkadur.fate.v1.lang.meta.Computation; import tonkadur.fate.v1.lang.meta.TextNode; public class Paragraph extends TextNode @@ -12,7 +13,7 @@ public class Paragraph extends TextNode /***************************************************************************/ /**** MEMBERS **************************************************************/ /***************************************************************************/ - protected final List content; + protected final List content; /***************************************************************************/ /**** PROTECTED ************************************************************/ @@ -26,7 +27,7 @@ public class Paragraph extends TextNode public Paragraph ( final Origin origin, - final List content + final List content ) { super(origin); @@ -42,7 +43,7 @@ public class Paragraph extends TextNode cv.visit_paragraph(this); } - public List get_content () + public List get_content () { return content; } @@ -55,7 +56,7 @@ public class Paragraph extends TextNode sb.append("(Paragraph "); - for (final TextNode text: content) + for (final Computation text: content) { sb.append(content.toString()); } diff --git a/src/core/src/tonkadur/fate/v1/lang/meta/VariableFromWord.java b/src/core/src/tonkadur/fate/v1/lang/meta/VariableFromWord.java index b6c933e..365e70a 100644 --- a/src/core/src/tonkadur/fate/v1/lang/meta/VariableFromWord.java +++ b/src/core/src/tonkadur/fate/v1/lang/meta/VariableFromWord.java @@ -10,7 +10,7 @@ import java.util.ArrayList; import tonkadur.parser.Origin; import tonkadur.parser.ParsingError; -import tonkadur.fate.v1.parser.Parser; +import tonkadur.fate.v1.parser.ParserData; import tonkadur.fate.v1.lang.Variable; import tonkadur.fate.v1.lang.computation.Constant; @@ -29,7 +29,7 @@ public class VariableFromWord public static Computation generate ( - final Parser parser, + final ParserData parser, final Origin origin, final String word ) diff --git a/src/core/src/tonkadur/fate/v1/lang/type/ExtraType.java b/src/core/src/tonkadur/fate/v1/lang/type/ExtraType.java index 8c48380..91543fc 100644 --- a/src/core/src/tonkadur/fate/v1/lang/type/ExtraType.java +++ b/src/core/src/tonkadur/fate/v1/lang/type/ExtraType.java @@ -1,15 +1,18 @@ package tonkadur.fate.v1.lang.type; +import java.util.List; + import tonkadur.parser.Origin; import tonkadur.fate.v1.lang.meta.DeclaredEntity; +import tonkadur.fate.v1.lang.meta.RecurrentChecks; public class ExtraType extends Type { /***************************************************************************/ /**** MEMBERS **************************************************************/ /***************************************************************************/ - + protected final List parameters; /***************************************************************************/ /**** PUBLIC ***************************************************************/ /***************************************************************************/ @@ -18,20 +21,26 @@ public class ExtraType extends Type public ExtraType ( final Origin origin, - final String name + final String name, + final List parameters ) { super(origin, null, name); + + this.parameters = parameters; } public ExtraType ( final Origin origin, final ExtraType parent, - final String name + final String name, + final List parameters ) { super(origin, parent, name); + + this.parameters = parameters; } /**** Accessors ************************************************************/ @@ -46,7 +55,24 @@ public class ExtraType extends Type e = (ExtraType) t; - return get_base_type().get_name().equals(e.get_base_type().get_name()); + if (get_base_type().get_name().equals(e.get_base_type().get_name())) + { + try + { + RecurrentChecks.assert_types_matches_signature + ( + Origin.BASE_LANGUAGE, + parameters, + e.parameters + ); + } + catch (final Throwable _e) + { + return false; + } + + return true; + } } @@ -76,7 +102,7 @@ public class ExtraType extends Type @Override public Type generate_alias (final Origin origin, final String name) { - return new ExtraType(origin, this, name); + return new ExtraType(origin, this, name, parameters); } @Override @@ -87,6 +113,13 @@ public class ExtraType extends Type sb.append("ExtraType::"); sb.append(name); + for (final Type t: parameters) + { + sb.append("<"); + sb.append(t.toString()); + 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 d211d03..a8a5d06 100644 --- a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 +++ b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 @@ -46,13 +46,13 @@ options @members { - Parser PARSER; + ParserData PARSER; } /******************************************************************************/ /******************************************************************************/ /******************************************************************************/ -fate_file [Parser PARSER] +fate_file [ParserData parser] @init { PARSER = parser; @@ -99,7 +99,7 @@ returns [List result] first_level_instruction @init { - Parser.LocalVariables previous_local_variables_stack; + ParserData.LocalVariables previous_local_variables_stack; } : DECLARE_ALIAS_TYPE_KW parent=type WS+ identifier WS* R_PAREN @@ -326,7 +326,7 @@ first_level_instruction { previous_local_variables_stack = PARSER.get_local_variables_stack(); PARSER.discard_local_variables_stack(); - PARSER.increase_local_variables_herarchy(); + PARSER.increase_local_variables_hierarchy(); } identifier WS* @@ -334,7 +334,7 @@ first_level_instruction L_PAREN WS* variable_list WS* R_PAREN { PARSER.add_local_variables(($variable_list.result).as_map()); - PARSER.increase_local_variables_herarchy(); + PARSER.increase_local_variables_hierarchy(); } ) pre_sequence_point=WS+ @@ -400,7 +400,7 @@ first_level_instruction { PARSER.add_file_content ( - PARSER.get_location_at + PARSER.get_origin_at ( ($REQUIRE_KW.getLine()), ($REQUIRE_KW.getCharPositionInLine()) @@ -418,7 +418,7 @@ first_level_instruction PARSER.add_file_content ( - PARSER.get_location_at + PARSER.get_origin_at ( ($INCLUDE_KW.getLine()), ($INCLUDE_KW.getCharPositionInLine()) @@ -818,11 +818,11 @@ returns [Instruction result] ($field_value_list.result) ) { - final FieldReference fr; + final FieldAccess fa; final Computation cp; - fr = - FieldReference.build + fa = + FieldAccess.build ( entry.get_car(), ($computation.result), @@ -831,9 +831,9 @@ returns [Instruction result] cp = entry.get_cdr().get_cdr(); - RecurrentChecks.assert_can_be_used_as(cp, fr.get_type()); + RecurrentChecks.assert_can_be_used_as(cp, fa.get_type()); - assignments.add(new Cons(fr.get_field_name(), cp)); + assignments.add(new Cons(fa.get_field_name(), cp)); } $result = @@ -854,7 +854,7 @@ returns [Instruction result] /******************************************************************************/ | PLAYER_CHOICE_KW - player_choice_list[Parser.generate_player_choice_data()] + player_choice_list[PARSER.generate_player_choice_data()] WS* R_PAREN { @@ -1033,7 +1033,7 @@ returns [List> result] } ; -player_choice_list [Parser.PlayerChoiceData pcd] +player_choice_list [ParserData.PlayerChoiceData pcd] returns [List result] @init { @@ -1052,7 +1052,7 @@ catch [final Throwable e] PARSER.handle_error(e); } -maybe_player_choice_list [Parser.PlayerChoiceData pcd] +maybe_player_choice_list [ParserData.PlayerChoiceData pcd] returns [List result] @init { @@ -1069,7 +1069,7 @@ returns [List result] } ; -player_choice [Parser.PlayerChoiceData pcd] +player_choice [ParserData.PlayerChoiceData pcd] returns [Instruction result] /* * Do not use a separate Local Variable stack for the player choice @@ -1080,7 +1080,7 @@ returns [Instruction result] TEXT_OPTION_KW L_PAREN WS* { - PARSER.enable_restricted_stack_of(pcd); + PARSER.enable_restricted_variable_stack_of(pcd); } paragraph WS* R_PAREN WS* @@ -1108,7 +1108,7 @@ returns [Instruction result] | EVENT_OPTION_KW { - PARSER.enable_restricted_stack_of(pcd); + PARSER.enable_restricted_variable_stack_of(pcd); } L_PAREN WS* WORD maybe_computation_list WS* R_PAREN WS* { @@ -1158,7 +1158,7 @@ returns [Instruction result] | IF_KW { - PARSER.enable_restricted_stack_of(pcd); + PARSER.enable_restricted_variable_stack_of(pcd); } computation WS* { @@ -1182,7 +1182,7 @@ returns [Instruction result] | IF_ELSE_KW { - PARSER.enable_restricted_stack_of(pcd); + PARSER.enable_restricted_variable_stack_of(pcd); } computation WS* { @@ -1222,7 +1222,7 @@ returns [Instruction result] | SWITCH_KW { - PARSER.enable_restricted_stack_of(pcd); + PARSER.enable_restricted_variable_stack_of(pcd); } computation WS* { @@ -1249,7 +1249,7 @@ returns [Instruction result] | FOR_KW l0=L_PAREN { - PARSER.enable_restricted_stack_of(pcd); + PARSER.enable_restricted_variable_stack_of(pcd); PARSER.increase_local_variables_hierarchy(); pcd.increase_variable_names_hierarchy(); } @@ -1266,7 +1266,7 @@ returns [Instruction result] R_PAREN { pcd.decrease_variable_names_hierarchy(); - PARSER.enable_restricted_stack_of(pcd); + PARSER.enable_restricted_variable_stack_of(pcd); PARSER.decrease_local_variables_hierarchy(); PARSER.disable_restricted_stack_of(pcd); @@ -1303,7 +1303,7 @@ returns [Instruction result] | FOR_EACH_KW { - PARSER.enable_restricted_stack_of(pcd); + PARSER.enable_restricted_variable_stack_of(pcd); PARSER.increase_local_variables_hierarchy(); } computation WS+ @@ -1363,7 +1363,7 @@ returns [Instruction result] player_choice_list[pcd] WS* R_PAREN { - PARSER.enable_restricted_stack_of(pcd); + PARSER.enable_restricted_variable_stack_of(pcd); PARSER.decrease_local_variables_hierarchy(); PARSER.disable_restricted_stack_of(pcd); $result = @@ -1385,7 +1385,7 @@ catch [final Throwable e] PARSER.handle_error(e); } -player_choice_cond_list [Parser.PlayerChoiceData pcd] +player_choice_cond_list [ParserData.PlayerChoiceData pcd] returns [List> result] @init { @@ -1394,7 +1394,7 @@ returns [List> result] condition = null; $result = new ArrayList>(); - PARSER.enable_restricted_stack_of(pcd); + PARSER.enable_restricted_variable_stack_of(pcd); } : ( @@ -1441,12 +1441,12 @@ catch [final Throwable e] PARSER.handle_error(e); } -player_choice_switch_list [Parser.PlayerChoiceData pcd] +player_choice_switch_list [ParserData.PlayerChoiceData pcd] returns [List> result] @init { $result = new ArrayList>(); - PARSER.enable_restricted_stack_of(pcd); + PARSER.enable_restricted_variable_stack_of(pcd); } : ( @@ -1471,17 +1471,21 @@ catch [final Throwable e] } paragraph -returns [TextNode result] +returns [Computation result] @init { - final List content = new ArrayList(); } : computation_list { // convert all computations to text. // return text node. - return new Paragraph(computation_list.result); + return + new Paragraph + ( + $computation_list.result.get(0).get_origin(), + $computation_list.result + ); } ; catch [final Throwable e] @@ -1557,7 +1561,7 @@ returns [Type result] ($identifier.result) ); - $result = t.build(type_list); + $result = t.build($type_list.result); } ; catch [final Throwable e] @@ -1648,7 +1652,7 @@ returns [List> result] false ); - PARSER.add_context_variable(v); + PARSER.add_local_variable(v); $result.add(new Cons(v, ($computation.result))); } @@ -1661,7 +1665,7 @@ catch [final Throwable e] PARSER.handle_error(e); } -choice_for_update_variable_list [Parser.PlayerChoiceData pcd] +choice_for_update_variable_list [ParserData.PlayerChoiceData pcd] returns [List result] @init { @@ -1737,7 +1741,7 @@ catch [final Throwable e] PARSER.handle_error(e); } -choice_for_variable_list [Parser.PlayerChoiceData pcd] +choice_for_variable_list [ParserData.PlayerChoiceData pcd] returns [List result] @init { @@ -1794,7 +1798,7 @@ returns [List result] $result.add(new LocalVariable(new_var)); - PARSER.add_context_variable(v); + PARSER.add_local_variable(new_var); $result.add ( @@ -1974,7 +1978,7 @@ computation returns [Computation result] @init { - Parser.LocalVariables previous_local_variables_stack; + ParserData.LocalVariables previous_local_variables_stack; } : WORD @@ -1997,7 +2001,7 @@ returns [Computation result] VariableFromWord.generate ( PARSER, - CONTEXT.get_origin_at + PARSER.get_origin_at ( ($WORD.getLine()), ($WORD.getCharPositionInLine()) @@ -2175,11 +2179,11 @@ returns [Computation result] ($field_value_list.result) ) { - final FieldReference fr; + final FieldAccess fa; final Computation cp; - fr = - FieldReference.build + fa = + FieldAccess.build ( entry.get_car(), ($computation.result), @@ -2188,9 +2192,9 @@ returns [Computation result] cp = entry.get_cdr().get_cdr(); - RecurrentChecks.assert_can_be_used_as(cp, fr.get_type()); + RecurrentChecks.assert_can_be_used_as(cp, fa.get_type()); - assignments.add(new Cons(fr.get_field_name(), cp)); + assignments.add(new Cons(fa.get_field_name(), cp)); } $result = diff --git a/src/core/src/tonkadur/fate/v1/parser/Parser.java b/src/core/src/tonkadur/fate/v1/parser/Parser.java deleted file mode 100644 index 4fc978d..0000000 --- a/src/core/src/tonkadur/fate/v1/parser/Parser.java +++ /dev/null @@ -1,312 +0,0 @@ -package tonkadur.fate.v1.parser; - -import java.io.IOException; - -import java.util.Collection; -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.HashSet; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import org.antlr.v4.runtime.CharStreams; -import org.antlr.v4.runtime.CommonTokenStream; - -import tonkadur.parser.Context; -import tonkadur.parser.Origin; - -import tonkadur.error.ErrorManager; - -import tonkadur.fate.v1.error.DuplicateLocalVariableException; - -import tonkadur.fate.v1.lang.Variable; -import tonkadur.fate.v1.lang.World; - -public class Parser -{ - protected final World world; - protected final Context context; - - protected LocalVariables local_variables; - - protected int breakable_levels; - protected int continue_levels; - - public Parser (final World world) - { - this.world = world; - - local_variables = new LocalVariables(); - - breakable_levels = 0; - continue_levels = 0; - - context = Context.BASE_LANGUAGE.clone(); - } - - public Origin get_origin_at (final int line, final int column) - { - return context.get_origin_at(line, column); - } - - public World get_world () - { - return world; - } - - public Context get_context () - { - return context; - } - - /**** BREAKABLE LEVELS *****************************************************/ - public boolean can_use_break () - { - return (breakable_levels > 0); - } - - public void increment_breakable_levels () - { - breakable_levels++; - } - - public void decrement_breakable_levels () - { - breakable_levels--; - } - - /**** CONTINUE LEVELS ******************************************************/ - public boolean can_use_continue () - { - return (continue_levels > 0); - } - - public void increment_continue_levels () - { - continue_levels++; - } - - public void decrement_continue_levels () - { - continue_levels--; - } - - /**** LOCAL VARIABLES ******************************************************/ - public Variable maybe_get_local_variable (final String name) - { - for (final Map level: local_variables.stack) - { - final Variable v; - - v = level.get(name); - - if (v != null) - { - return v; - } - } - - return null; - } - - public void add_local_variables (final Map collection) - throws Throwable - { - for (final Variable variable: collection.values()) - { - add_local_variable(variable); - } - } - - public void add_local_variable (final Variable variable) - throws Throwable - { - final Map current_hierarchy; - final Variable previous_entry; - - current_hierarchy = local_variables.stack.peek(); - previous_entry = current_hierarchy.get(variable.get_name()); - - if (previous_entry != null) - { - ErrorManager.handle - ( - new DuplicateLocalVariableException - ( - previous_entry, - variable - ) - ); - } - - current_hierarchy.put(variable.get_name(), variable); - } - - public void increase_local_variables_hierarchy () - { - local_variables.stack.push(new HashMap()); - } - - public void decrease_local_variables_hierarchy () - { - local_variables.stack.pop(); - } - - /* I don't think it's needed ATM. */ - public Collection get_local_variables_at_current_hierarchy () - { - return local_variables.stack.peek().values(); - } - - public LocalVariables get_local_variables_stack () - { - return local_variables; - } - - public void restore_local_variables_stack - ( - final LocalVariables local_variables - ) - { - this.local_variables = local_variables; - } - - public void discard_local_variables_stack () - { - local_variables = new LocalVariables(); - } - - /**** ERROR HANDLING *******************************************************/ - public void handle_error (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); - } - } - - public void add_file_content (final Origin origin, final String filename) - throws IOException - { - final CommonTokenStream tokens; - final FateLexer lexer; - final FateParser parser; - - lexer = new FateLexer(CharStreams.fromFileName(filename)); - tokens = new CommonTokenStream(lexer); - parser = new FateParser(tokens); - - context.push(origin.get_location(), filename); - parser.fate_file(this); - context.pop(); - - world.add_loaded_file(filename); - - if (parser.getNumberOfSyntaxErrors() > 0) - { - throw new IOException("There were syntaxic errors in " + filename); - } - } - - public PlayerChoiceData generate_player_choice_data () - { - return new Parser.PlayerChoiceData(this); - } - - public void enable_restricted_variable_stack_of (final PlayerChoiceData pcd) - { - pcd.previous_variable_stack = get_local_variables_stack(); - - restore_local_variables_stack(pcd.restricted_including_variables_stack); - } - - public void disable_restricted_stack_of (final PlayerChoiceData pcd) - { - restore_local_variables_stack(pcd.previous_variable_stack); - } - - - /* Internal class to make moving LocalVariable objects around easier. */ - public static class LocalVariables - { - protected final Deque> stack; - - protected LocalVariables () - { - stack = new ArrayDeque>(); - } - - protected LocalVariables (final Deque> stack) - { - this.stack = stack.clone(); - } - - @Override - public LocalVariables clone () - { - return new LocalVariables(stack); - } - } - - public static class PlayerChoiceData - { - protected final Parser parent; - protected final LocalVariables restricted_including_variables_stack; - protected LocalVariables previous_variable_stack; - protected final Deque> player_choice_variable_names; - - protected PlayerChoiceData (final Parser parent) - { - this.parent = parent; - - previous_variable_stack = parent.get_local_variables_stack(); - - // Note: clone makes a shallow copy. - restricted_including_variables_stack = previous_variable_stack.clone(); - - player_choice_variable_names = new ArrayDeque>(); - } - - public void increase_variable_names_hierarchy () - { - player_choice_variable_names.push(new HashSet()); - } - - public void decrease_variable_names_hierarchy () - { - player_choice_variable_names.pop(); - } - - public void mark_name_as_editable (final String name) - { - player_choice_variable_names.peek().add(name); - } - - public boolean can_update_variable (final String name) - { - for (final Set variable_names: player_choice_variable_names) - { - if (variable_names.contains(name)) - { - return true; - } - } - - return false; - } - } -} diff --git a/src/core/src/tonkadur/fate/v1/parser/ParserData.java b/src/core/src/tonkadur/fate/v1/parser/ParserData.java new file mode 100644 index 0000000..45ef985 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/parser/ParserData.java @@ -0,0 +1,315 @@ +package tonkadur.fate.v1.parser; + +import java.io.IOException; + +import java.util.Collection; +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.HashSet; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.antlr.v4.runtime.CharStreams; +import org.antlr.v4.runtime.CommonTokenStream; +import org.antlr.v4.runtime.misc.ParseCancellationException; + + +import tonkadur.parser.Context; +import tonkadur.parser.Origin; + +import tonkadur.error.ErrorManager; + +import tonkadur.fate.v1.error.DuplicateLocalVariableException; + +import tonkadur.fate.v1.lang.Variable; +import tonkadur.fate.v1.lang.World; + +public class ParserData +{ + protected final World world; + protected final Context context; + + protected LocalVariables local_variables; + + protected int breakable_levels; + protected int continue_levels; + + public ParserData (final World world) + { + this.world = world; + + local_variables = new LocalVariables(); + + breakable_levels = 0; + continue_levels = 0; + + context = Context.BASE_LANGUAGE.clone(); + } + + public Origin get_origin_at (final int line, final int column) + { + return context.get_origin_at(line, column); + } + + public World get_world () + { + return world; + } + + public Context get_context () + { + return context; + } + + /**** BREAKABLE LEVELS *****************************************************/ + public boolean can_use_break () + { + return (breakable_levels > 0); + } + + public void increment_breakable_levels () + { + breakable_levels++; + } + + public void decrement_breakable_levels () + { + breakable_levels--; + } + + /**** CONTINUE LEVELS ******************************************************/ + public boolean can_use_continue () + { + return (continue_levels > 0); + } + + public void increment_continue_levels () + { + continue_levels++; + } + + public void decrement_continue_levels () + { + continue_levels--; + } + + /**** LOCAL VARIABLES ******************************************************/ + public Variable maybe_get_local_variable (final String name) + { + for (final Map level: local_variables.stack) + { + final Variable v; + + v = level.get(name); + + if (v != null) + { + return v; + } + } + + return null; + } + + public void add_local_variables (final Map collection) + throws Throwable + { + for (final Variable variable: collection.values()) + { + add_local_variable(variable); + } + } + + public void add_local_variable (final Variable variable) + throws Throwable + { + final Map current_hierarchy; + final Variable previous_entry; + + current_hierarchy = local_variables.stack.peek(); + previous_entry = current_hierarchy.get(variable.get_name()); + + if (previous_entry != null) + { + ErrorManager.handle + ( + new DuplicateLocalVariableException + ( + previous_entry, + variable + ) + ); + } + + current_hierarchy.put(variable.get_name(), variable); + } + + public void increase_local_variables_hierarchy () + { + local_variables.stack.push(new HashMap()); + } + + public void decrease_local_variables_hierarchy () + { + local_variables.stack.pop(); + } + + /* I don't think it's needed ATM. */ + public Collection get_local_variables_at_current_hierarchy () + { + return local_variables.stack.peek().values(); + } + + public LocalVariables get_local_variables_stack () + { + return local_variables; + } + + public void restore_local_variables_stack + ( + final LocalVariables local_variables + ) + { + this.local_variables = local_variables; + } + + public void discard_local_variables_stack () + { + local_variables = new LocalVariables(); + } + + /**** ERROR HANDLING *******************************************************/ + public void handle_error (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); + } + } + + public void add_file_content (final Origin origin, final String filename) + throws IOException + { + final CommonTokenStream tokens; + final FateLexer lexer; + final FateParser parser; + + lexer = new FateLexer(CharStreams.fromFileName(filename)); + tokens = new CommonTokenStream(lexer); + parser = new FateParser(tokens); + + context.push(origin.get_location(), filename); + parser.fate_file(this); + context.pop(); + + world.add_loaded_file(filename); + + if (parser.getNumberOfSyntaxErrors() > 0) + { + throw new IOException("There were syntaxic errors in " + filename); + } + } + + public PlayerChoiceData generate_player_choice_data () + { + return new ParserData.PlayerChoiceData(this); + } + + public void enable_restricted_variable_stack_of (final PlayerChoiceData pcd) + { + pcd.previous_variable_stack = get_local_variables_stack(); + + restore_local_variables_stack(pcd.restricted_including_variables_stack); + } + + public void disable_restricted_stack_of (final PlayerChoiceData pcd) + { + restore_local_variables_stack(pcd.previous_variable_stack); + } + + + /* Internal class to make moving LocalVariable objects around easier. */ + public static class LocalVariables + { + // Can't clone if declared as Deque + protected final ArrayDeque> stack; + + protected LocalVariables () + { + stack = new ArrayDeque>(); + } + + protected LocalVariables (final ArrayDeque> stack) + { + this.stack = stack.clone(); + } + + @Override + public LocalVariables clone () + { + return new LocalVariables(stack); + } + } + + public static class PlayerChoiceData + { + protected final ParserData parent; + protected final LocalVariables restricted_including_variables_stack; + protected LocalVariables previous_variable_stack; + protected final Deque> player_choice_variable_names; + + protected PlayerChoiceData (final ParserData parent) + { + this.parent = parent; + + previous_variable_stack = parent.get_local_variables_stack(); + + // Note: clone makes a shallow copy. + restricted_including_variables_stack = previous_variable_stack.clone(); + + player_choice_variable_names = new ArrayDeque>(); + } + + public void increase_variable_names_hierarchy () + { + player_choice_variable_names.push(new HashSet()); + } + + public void decrease_variable_names_hierarchy () + { + player_choice_variable_names.pop(); + } + + public void mark_name_as_editable (final String name) + { + player_choice_variable_names.peek().add(name); + } + + public boolean can_update_variable (final String name) + { + for (final Set variable_names: player_choice_variable_names) + { + if (variable_names.contains(name)) + { + return true; + } + } + + return false; + } + } +} -- cgit v1.2.3-70-g09d2