| summaryrefslogtreecommitdiff |
diff options
| author | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2020-07-17 20:49:49 +0200 |
|---|---|---|
| committer | Nathanael Sensfelder <SpamShield0@MultiAgentSystems.org> | 2020-07-17 20:49:49 +0200 |
| commit | f1b045e03a7a5f3d9d4b94c5e4d41359ee77a594 (patch) | |
| tree | bb88538e14921ebbe61f6638d753afd527be8210 | |
| parent | e1ee2f20d251a5c48d1b94de8a67f2440af66ec5 (diff) | |
Slowly adding Fate content...
| -rw-r--r-- | src/core/src/tonkadur/fate/v1/error/UnknownSequenceException.java | 73 | ||||
| -rw-r--r-- | src/core/src/tonkadur/fate/v1/lang/CountOperator.java | 144 | ||||
| -rw-r--r-- | src/core/src/tonkadur/fate/v1/lang/InstructionList.java | 57 | ||||
| -rw-r--r-- | src/core/src/tonkadur/fate/v1/lang/IsMemberOperator.java | 144 | ||||
| -rw-r--r-- | src/core/src/tonkadur/fate/v1/lang/Sequence.java | 94 | ||||
| -rw-r--r-- | src/core/src/tonkadur/fate/v1/lang/SequenceCall.java | 43 | ||||
| -rw-r--r-- | src/core/src/tonkadur/fate/v1/lang/Type.java | 6 | ||||
| -rw-r--r-- | src/core/src/tonkadur/fate/v1/lang/World.java | 93 | ||||
| -rw-r--r-- | src/core/src/tonkadur/fate/v1/parser/FateParser.g4 | 131 |
9 files changed, 751 insertions, 34 deletions
diff --git a/src/core/src/tonkadur/fate/v1/error/UnknownSequenceException.java b/src/core/src/tonkadur/fate/v1/error/UnknownSequenceException.java new file mode 100644 index 0000000..8a617f9 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/error/UnknownSequenceException.java @@ -0,0 +1,73 @@ +package tonkadur.fate.v1.error; + +import java.util.Collection; + +import tonkadur.error.ErrorLevel; + +import tonkadur.parser.Origin; +import tonkadur.parser.ParsingError; + +public class UnknownSequenceException extends ParsingError +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final Collection<Origin> all_occurrences; + protected final String sequence_name; + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + public UnknownSequenceException + ( + final Origin first_occurrence, + final String sequence_name, + final Collection<Origin> all_occurrences + ) + { + super + ( + ErrorLevel.ERROR, + ErrorCategory.UNKNOWN, + first_occurrence + ); + + this.sequence_name = sequence_name; + this.all_occurrences = all_occurrences; + } + + @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("Unknown sequence '"); + sb.append(sequence_name); + sb.append("'. "); + sb.append(System.lineSeparator()); + + if (all_occurrences != null) + { + sb.append("Here is a complete list of all calls to this sequence:"); + sb.append(System.lineSeparator()); + + for (final Origin occurrence: all_occurrences) + { + /* + * Because sequences can be defined at any point, the context does + * not matter much, so let's just point out locations instead. + */ + sb.append("- "); + sb.append(occurrence.get_location().toString()); + sb.append(System.lineSeparator()); + } + } + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/CountOperator.java b/src/core/src/tonkadur/fate/v1/lang/CountOperator.java new file mode 100644 index 0000000..eabbe5c --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/CountOperator.java @@ -0,0 +1,144 @@ +package tonkadur.fate.v1.lang; + +import tonkadur.error.ErrorManager; + +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.lang.meta.ValueNode; + +import tonkadur.fate.v1.error.ConflictingTypeException; +import tonkadur.fate.v1.error.IncomparableTypeException; +import tonkadur.fate.v1.error.InvalidTypeException; + +public class CountOperator extends ValueNode +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final ValueNode element; + protected final ValueNode collection; + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + protected CountOperator + ( + final Origin origin, + final ValueNode element, + final ValueNode collection + ) + { + super(origin, Type.INT); + + this.collection = collection; + this.element = element; + } + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public static CountOperator build + ( + final Origin origin, + final ValueNode element, + final ValueNode collection + ) + throws + InvalidTypeException, + ConflictingTypeException, + IncomparableTypeException + { + final Type hint; + final Type collection_type; + final CollectionType collection_true_type; + final Type collection_element_type; + + collection_type = collection.get_type(); + + if + ( + !Type.COLLECTION_TYPES.contains(collection_type.get_base_type()) + || !(collection_type instanceof CollectionType) + ) + { + ErrorManager.handle + ( + new InvalidTypeException + ( + collection.get_origin(), + collection.get_type(), + Type.COLLECTION_TYPES + ) + ); + } + + collection_true_type = (CollectionType) collection_type; + collection_element_type = collection_true_type.get_content_type(); + + if (element.get_type().can_be_used_as(collection_element_type)) + { + return new CountOperator(origin, element, collection); + } + + ErrorManager.handle + ( + new ConflictingTypeException + ( + element.get_origin(), + element.get_type(), + collection_element_type + ) + ); + + hint = + (Type) element.get_type().generate_comparable_to + ( + collection_element_type + ); + + if (hint.equals(Type.ANY)) + { + ErrorManager.handle + ( + new IncomparableTypeException + ( + element.get_origin(), + element.get_type(), + collection_element_type + ) + ); + } + + return new CountOperator(origin, element, collection); + } + + /**** Accessors ************************************************************/ + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append(origin.toString()); + sb.append("(CountOperator"); + sb.append(System.lineSeparator()); + sb.append(System.lineSeparator()); + + sb.append("element:"); + sb.append(System.lineSeparator()); + sb.append(element.toString()); + sb.append(System.lineSeparator()); + sb.append(System.lineSeparator()); + + sb.append("collection:"); + sb.append(System.lineSeparator()); + sb.append(collection.toString()); + + sb.append(")"); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/InstructionList.java b/src/core/src/tonkadur/fate/v1/lang/InstructionList.java new file mode 100644 index 0000000..ee85120 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/InstructionList.java @@ -0,0 +1,57 @@ +package tonkadur.fate.v1.lang; + +import java.util.List; + +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.lang.meta.InstructionNode; + +public class InstructionList extends InstructionNode +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final List<InstructionNode> instructions; + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public InstructionList + ( + final Origin origin, + final List<InstructionNode> instructions + ) + { + super(origin); + + this.instructions = instructions; + } + + /**** Accessors ************************************************************/ + public List<InstructionNode> get_instructions () + { + return instructions; + } + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append("(InstructionList "); + + sb.append(System.lineSeparator()); + + for (final InstructionNode instruction: instructions) + { + sb.append(instruction.toString()); + sb.append(System.lineSeparator()); + } + + sb.append(")"); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/IsMemberOperator.java b/src/core/src/tonkadur/fate/v1/lang/IsMemberOperator.java new file mode 100644 index 0000000..3120c6c --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/IsMemberOperator.java @@ -0,0 +1,144 @@ +package tonkadur.fate.v1.lang; + +import tonkadur.error.ErrorManager; + +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.lang.meta.ValueNode; + +import tonkadur.fate.v1.error.ConflictingTypeException; +import tonkadur.fate.v1.error.IncomparableTypeException; +import tonkadur.fate.v1.error.InvalidTypeException; + +public class IsMemberOperator extends ValueNode +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final ValueNode element; + protected final ValueNode collection; + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + protected IsMemberOperator + ( + final Origin origin, + final ValueNode element, + final ValueNode collection + ) + { + super(origin, Type.BOOLEAN); + + this.collection = collection; + this.element = element; + } + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public static IsMemberOperator build + ( + final Origin origin, + final ValueNode element, + final ValueNode collection + ) + throws + InvalidTypeException, + ConflictingTypeException, + IncomparableTypeException + { + final Type hint; + final Type collection_type; + final CollectionType collection_true_type; + final Type collection_element_type; + + collection_type = collection.get_type(); + + if + ( + !Type.COLLECTION_TYPES.contains(collection_type.get_base_type()) + || !(collection_type instanceof CollectionType) + ) + { + ErrorManager.handle + ( + new InvalidTypeException + ( + collection.get_origin(), + collection.get_type(), + Type.COLLECTION_TYPES + ) + ); + } + + collection_true_type = (CollectionType) collection_type; + collection_element_type = collection_true_type.get_content_type(); + + if (element.get_type().can_be_used_as(collection_element_type)) + { + return new IsMemberOperator(origin, element, collection); + } + + ErrorManager.handle + ( + new ConflictingTypeException + ( + element.get_origin(), + element.get_type(), + collection_element_type + ) + ); + + hint = + (Type) element.get_type().generate_comparable_to + ( + collection_element_type + ); + + if (hint.equals(Type.ANY)) + { + ErrorManager.handle + ( + new IncomparableTypeException + ( + element.get_origin(), + element.get_type(), + collection_element_type + ) + ); + } + + return new IsMemberOperator(origin, element, collection); + } + + /**** Accessors ************************************************************/ + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append(origin.toString()); + sb.append("(IsMemberOperator"); + sb.append(System.lineSeparator()); + sb.append(System.lineSeparator()); + + sb.append("element:"); + sb.append(System.lineSeparator()); + sb.append(element.toString()); + sb.append(System.lineSeparator()); + sb.append(System.lineSeparator()); + + sb.append("collection:"); + sb.append(System.lineSeparator()); + sb.append(collection.toString()); + + sb.append(")"); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/Sequence.java b/src/core/src/tonkadur/fate/v1/lang/Sequence.java new file mode 100644 index 0000000..8029c61 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/Sequence.java @@ -0,0 +1,94 @@ +package tonkadur.fate.v1.lang; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import tonkadur.error.ErrorManager; + +import tonkadur.parser.Context; +import tonkadur.parser.Location; +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.error.InvalidTypeException; + +import tonkadur.fate.v1.lang.meta.DeclaredEntity; +import tonkadur.fate.v1.lang.meta.InstructionNode; + +public class Sequence extends DeclaredEntity +{ + @Override + public /* static */ String get_type_name () + { + return "Sequence"; + } + + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final InstructionNode root; + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + + /**** Constructors *********************************************************/ + public Sequence + ( + final Origin origin, + final InstructionNode root, + final String name + ) + { + super(origin, name); + + this.root = root; + } + + /**** Accessors ************************************************************/ + public InstructionNode get_root () + { + return root; + } + + /**** Compatibility ********************************************************/ + + /* + * This is for the very special case where a type is used despite not being + * even a sub-type of the expected one. Using this rather expensive function, + * the most restrictive shared type will be returned. If no such type exists, + * the ANY time is returned. + */ + @Override + public DeclaredEntity generate_comparable_to (final DeclaredEntity de) + { + return null; + } + + + /**** Misc. ****************************************************************/ + @Override + public boolean is_incompatible_with_declaration (final DeclaredEntity de) + { + return true; + } + + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append("(Sequence "); + sb.append(name); + sb.append(")"); + + return sb.toString(); + } + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ +} diff --git a/src/core/src/tonkadur/fate/v1/lang/SequenceCall.java b/src/core/src/tonkadur/fate/v1/lang/SequenceCall.java new file mode 100644 index 0000000..5b0df50 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/SequenceCall.java @@ -0,0 +1,43 @@ +package tonkadur.fate.v1.lang; + +import tonkadur.parser.Origin; + +import tonkadur.fate.v1.lang.meta.InstructionNode; + +public class SequenceCall extends InstructionNode +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final String sequence_name; + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + /**** Constructors *********************************************************/ + public SequenceCall (final Origin origin, final String sequence_name) + { + super(origin); + + this.sequence_name = sequence_name; + } + + /**** Accessors ************************************************************/ + public String get_sequence_name () + { + return sequence_name; + } + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append("(SequenceCall "); + sb.append(sequence_name); + sb.append(")"); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/Type.java b/src/core/src/tonkadur/fate/v1/lang/Type.java index 129f08b..cbbeb42 100644 --- a/src/core/src/tonkadur/fate/v1/lang/Type.java +++ b/src/core/src/tonkadur/fate/v1/lang/Type.java @@ -31,6 +31,7 @@ public class Type extends DeclaredEntity public static final Set<Type> NUMBER_TYPES; public static final Set<Type> SIMPLE_BASE_TYPES; + public static final Set<Type> COLLECTION_TYPES; static { @@ -63,6 +64,11 @@ public class Type extends DeclaredEntity SIMPLE_BASE_TYPES.add(STRING); SIMPLE_BASE_TYPES.add(BOOLEAN); SIMPLE_BASE_TYPES.add(REF); + + COLLECTION_TYPES = new HashSet<Type>(); + + COLLECTION_TYPES.add(SET); + COLLECTION_TYPES.add(LIST); } public static Type value_on_missing () diff --git a/src/core/src/tonkadur/fate/v1/lang/World.java b/src/core/src/tonkadur/fate/v1/lang/World.java index d71dfe8..76b7805 100644 --- a/src/core/src/tonkadur/fate/v1/lang/World.java +++ b/src/core/src/tonkadur/fate/v1/lang/World.java @@ -1,15 +1,24 @@ package tonkadur.fate.v1.lang; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; +import tonkadur.error.ErrorManager; + import tonkadur.parser.Context; import tonkadur.parser.Location; import tonkadur.parser.Origin; +import tonkadur.fate.v1.error.UnknownSequenceException; + import tonkadur.fate.v1.lang.meta.DeclarationCollection; + public class World { /***************************************************************************/ @@ -17,9 +26,12 @@ public class World /***************************************************************************/ protected final Set<String> loaded_files; protected final Set<String> required_extensions; + + protected final Map<String, List<Origin>> sequence_calls; + protected final DeclarationCollection<Event> event_collection; // protected final DeclarationCollection<Macro> macros; -// protected final DeclarationCollection<Sequence> sequences; + protected final DeclarationCollection<Sequence> sequence_collection; protected final DeclarationCollection<TextEffect> text_effect_collection; protected final DeclarationCollection<Type> type_collection; protected final DeclarationCollection<Variable> variable_collection; @@ -33,11 +45,13 @@ public class World { loaded_files = new HashSet<String>(); required_extensions = new HashSet<String>(); + sequence_calls = new HashMap<String, List<Origin>>(); event_collection = new DeclarationCollection<Event>(Event.value_on_missing()); //macros = new DeclarationCollection<Macro>(); - //sequences = new DeclarationCollection<Sequence>(); + sequence_collection = new DeclarationCollection<Sequence>(null); + text_effect_collection = new DeclarationCollection<TextEffect>(TextEffect.value_on_missing()); type_collection = @@ -81,12 +95,34 @@ public class World required_extensions.add(name); } + /**** Sequence Calls ****/ + public void add_sequence_call (final Origin origin, final String sequence) + { + List<Origin> list_of_calls; + + list_of_calls = sequence_calls.get(sequence); + + if (list_of_calls == null) + { + list_of_calls = new ArrayList<Origin>(); + + sequence_calls.put(sequence, list_of_calls); + } + + list_of_calls.add(origin); + } + /**** Collections ****/ public DeclarationCollection<Event> events () { return event_collection; } + public DeclarationCollection<Sequence> sequences () + { + return sequence_collection; + } + public DeclarationCollection<TextEffect> text_effects () { return text_effect_collection; @@ -103,6 +139,19 @@ public class World } /**** Misc. ****************************************************************/ + + public boolean assert_sanity () + throws UnknownSequenceException + { + boolean is_sane; + + is_sane = true; + + is_sane = assert_sane_sequence_calls() & is_sane; + + return is_sane; + } + @Override public String toString () { @@ -182,6 +231,46 @@ public class World System.err.println("Unable to add base types:" + t.toString()); System.exit(-1); } + } + + protected boolean assert_sane_sequence_calls () + throws UnknownSequenceException + { + boolean is_sane; + + is_sane = true; + + for + ( + final Map.Entry<String, List<Origin>> entry: + sequence_calls.entrySet() + ) + { + if (!sequences().has(entry.getKey())) + { + final List<Origin> occurrences; + + occurrences = entry.getValue(); + + if (occurrences.isEmpty()) + { + continue; + } + + is_sane = false; + + ErrorManager.handle + ( + new UnknownSequenceException + ( + occurrences.get(0), + entry.getKey(), + ((occurrences.size() == 1) ? null : occurrences) + ) + ); + } + } + return is_sane; } } diff --git a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 index b665211..8f84217 100644 --- a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 +++ b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 @@ -60,8 +60,19 @@ fate_file [Context context, World world] } ; -general_fate_sequence: - (WS* general_fate_instr WS*)* +general_fate_sequence +returns [List<InstructionNode> result] +@init +{ + $result = new ArrayList<InstructionNode>(); +} +: + (WS* + general_fate_instr + { + $result.add($general_fate_instr.result); + } + WS*)* { /* TODO */ } @@ -71,23 +82,41 @@ first_level_fate_instr: DEFINE_SEQUENCE_KW WS+ new_reference_name - WS+ - first_node=general_fate_sequence + pre_sequence_point=WS+ + general_fate_sequence WS* R_PAREN { - /* - world.sequences().add - ( + final Origin start_origin, sequence_origin; + final Sequence new_sequence; + + start_origin = CONTEXT.get_origin_at ( ($DEFINE_SEQUENCE_KW.getLine()), ($DEFINE_SEQUENCE_KW.getCharPositionInLine()) - ), - ($new_reference_name.result), - //(first_node.result) - ); - */ + ); + + sequence_origin = + CONTEXT.get_origin_at + ( + ($pre_sequence_point.getLine()), + ($pre_sequence_point.getCharPositionInLine()) + ); + + new_sequence = + new Sequence + ( + start_origin, + new InstructionList + ( + sequence_origin, + ($general_fate_sequence.result) + ), + ($new_reference_name.result) + ); + + WORLD.sequences().add(new_sequence); } | DECLARE_VARIABLE_KW @@ -313,20 +342,6 @@ first_level_fate_instr: WORLD.types().add(new_type); } - | ADD_KW WS+ value WS+ value_reference WS* R_PAREN - { - /* TODO */ - } - - | REMOVE_ONE_KW WS+ value WS+ value_reference WS* R_PAREN - { - /* TODO */ - } - - | REMOVE_ALL_KW WS+ value WS+ value_reference WS* R_PAREN - { - /* TODO */ - } | DECLARE_EVENT_TYPE_KW WS+ new_reference_name WS+ type_list WS* R_PAREN { @@ -424,7 +439,31 @@ returns [InstructionNode result] { /* TODO */ - $result = null; + $result = + new InstructionList + ( + CONTEXT.get_origin_at + ( + ($L_PAREN.getLine()), + ($L_PAREN.getCharPositionInLine()) + ), + ($general_fate_sequence.result) + ); + } + + | ADD_KW WS+ value WS+ value_reference WS* R_PAREN + { + /* TODO */ + } + + | REMOVE_ONE_KW WS+ value WS+ value_reference WS* R_PAREN + { + /* TODO */ + } + + | REMOVE_ALL_KW WS+ value WS+ value_reference WS* R_PAREN + { + /* TODO */ } | CLEAR_KW WS+ value_reference WS* R_PAREN @@ -472,9 +511,21 @@ returns [InstructionNode result] | SEQUENCE_KW WS+ WORD WS* R_PAREN { - /* TODO */ + final Origin origin; + final String sequence_name; - $result = null; + origin = + CONTEXT.get_origin_at + ( + ($SEQUENCE_KW.getLine()), + ($SEQUENCE_KW.getCharPositionInLine()) + ); + + sequence_name = ($WORD.text); + + WORLD.add_sequence_call(origin, sequence_name); + + $result = new SequenceCall(origin, sequence_name); } | ASSERT_KW WS+ value WS* R_PAREN @@ -1051,8 +1102,17 @@ returns [ValueNode result]: | COUNT_KW WS+ value WS+ value_reference WS* R_PAREN { - /* TODO */ - $result= null; + $result = + CountOperator.build + ( + CONTEXT.get_origin_at + ( + ($COUNT_KW.getLine()), + ($COUNT_KW.getCharPositionInLine()) + ), + ($value.result), + ($value_reference.result) + ); } ; catch [final Throwable e] @@ -1161,7 +1221,14 @@ returns [ValueNode result] | EXTENSION_VALUE_KW WORD WS+ general_fate_sequence WS* R_PAREN { - /* TODO: no param alternative. */ + /* TODO */ + /* Extension stuff */ + System.out.println("Using extension value " + ($WORD.text)); + } + + | EXTENSION_VALUE_KW WORD WS* R_PAREN + { + /* TODO */ /* Extension stuff */ System.out.println("Using extension value " + ($WORD.text)); } |


