summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/src/tonkadur/fate/v1/error/DuplicateFieldException.java55
-rw-r--r--src/core/src/tonkadur/fate/v1/error/IllegalReferenceNameException.java46
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/World.java2
-rw-r--r--src/core/src/tonkadur/fate/v1/lang/meta/TypedEntryList.java89
-rw-r--r--src/core/src/tonkadur/fate/v1/parser/FateParser.g4148
5 files changed, 320 insertions, 20 deletions
diff --git a/src/core/src/tonkadur/fate/v1/error/DuplicateFieldException.java b/src/core/src/tonkadur/fate/v1/error/DuplicateFieldException.java
new file mode 100644
index 0000000..1b84840
--- /dev/null
+++ b/src/core/src/tonkadur/fate/v1/error/DuplicateFieldException.java
@@ -0,0 +1,55 @@
+package tonkadur.fate.v1.error;
+
+import tonkadur.error.ErrorLevel;
+
+import tonkadur.parser.Origin;
+import tonkadur.parser.ParsingError;
+
+public class DuplicateFieldException extends ParsingError
+{
+ /***************************************************************************/
+ /**** MEMBERS **************************************************************/
+ /***************************************************************************/
+ protected final Origin previous_definition;
+ protected final String name;
+
+ /***************************************************************************/
+ /**** PUBLIC ***************************************************************/
+ /***************************************************************************/
+ public DuplicateFieldException
+ (
+ final Origin new_origin,
+ final Origin previous_definition,
+ final String name
+ )
+ {
+ super
+ (
+ ErrorLevel.ERROR,
+ ErrorCategory.INVALID_USE,
+ new_origin
+ );
+
+ this.previous_definition = previous_definition;
+ this.name = 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("Duplicate field '");
+ sb.append(name);
+ sb.append("'. It was previously defined at ");
+ sb.append(previous_definition.get_location().toString());
+ sb.append(".");
+
+ return sb.toString();
+ }
+}
diff --git a/src/core/src/tonkadur/fate/v1/error/IllegalReferenceNameException.java b/src/core/src/tonkadur/fate/v1/error/IllegalReferenceNameException.java
new file mode 100644
index 0000000..8cff054
--- /dev/null
+++ b/src/core/src/tonkadur/fate/v1/error/IllegalReferenceNameException.java
@@ -0,0 +1,46 @@
+package tonkadur.fate.v1.error;
+
+import java.util.Map;
+
+import tonkadur.error.ErrorLevel;
+
+import tonkadur.parser.Origin;
+import tonkadur.parser.ParsingError;
+
+public class IllegalReferenceNameException extends ParsingError
+{
+ /***************************************************************************/
+ /**** MEMBERS **************************************************************/
+ /***************************************************************************/
+ protected final String name;
+
+ /***************************************************************************/
+ /**** PUBLIC ***************************************************************/
+ /***************************************************************************/
+ public IllegalReferenceNameException
+ (
+ final Origin origin,
+ final String name
+ )
+ {
+ super(ErrorLevel.ERROR, ErrorCategory.INVALID_USE, origin);
+ this.name = 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("Illegal use of '.' ('");
+ sb.append(name);
+ sb.append("').");
+
+ return sb.toString();
+ }
+}
diff --git a/src/core/src/tonkadur/fate/v1/lang/World.java b/src/core/src/tonkadur/fate/v1/lang/World.java
index edfb6fa..d323457 100644
--- a/src/core/src/tonkadur/fate/v1/lang/World.java
+++ b/src/core/src/tonkadur/fate/v1/lang/World.java
@@ -151,7 +151,7 @@ public class World
sb.append(System.lineSeparator());
sb.append(System.lineSeparator());
- sb.append("Variable: ");
+ sb.append("Variables: ");
sb.append(System.lineSeparator());
sb.append(variable_collection.toString());
sb.append(System.lineSeparator());
diff --git a/src/core/src/tonkadur/fate/v1/lang/meta/TypedEntryList.java b/src/core/src/tonkadur/fate/v1/lang/meta/TypedEntryList.java
new file mode 100644
index 0000000..b8ad468
--- /dev/null
+++ b/src/core/src/tonkadur/fate/v1/lang/meta/TypedEntryList.java
@@ -0,0 +1,89 @@
+package tonkadur.fate.v1.lang.meta;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import tonkadur.parser.Origin;
+
+import tonkadur.error.ErrorManager;
+
+import tonkadur.fate.v1.error.DuplicateFieldException;
+
+import tonkadur.fate.v1.lang.Type;
+
+public class TypedEntryList
+{
+ protected final Map<String, Origin> entry_origins;
+ protected final List<TypedEntry> entries;
+
+ public TypedEntryList ()
+ {
+ entry_origins = new HashMap<String, Origin>();
+ entries = new ArrayList<TypedEntry>();
+ }
+
+ public void add
+ (
+ final Origin origin,
+ final Type type,
+ final String name
+ )
+ throws DuplicateFieldException
+ {
+ final Origin previous_origin;
+
+ previous_origin = entry_origins.get(name);
+
+ if (previous_origin != null)
+ {
+ ErrorManager.handle
+ (
+ new DuplicateFieldException(origin, previous_origin, name)
+ );
+ }
+
+ entry_origins.put(name, origin);
+ entries.add(new TypedEntry(origin, type, name));
+ }
+
+ public List<TypedEntry> get_entries ()
+ {
+ return entries;
+ }
+
+ public static class TypedEntry
+ {
+ protected final Origin origin;
+ protected final Type type;
+ protected final String name;
+
+ protected TypedEntry
+ (
+ final Origin origin,
+ final Type type,
+ final String name
+ )
+ {
+ this.origin = origin;
+ this.type = type;
+ this.name = name;
+ }
+
+ public String get_name ()
+ {
+ return name;
+ }
+
+ public Type get_type ()
+ {
+ return type;
+ }
+
+ public Origin get_origin ()
+ {
+ return origin;
+ }
+ }
+}
diff --git a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4
index 2b581e7..aa20ad6 100644
--- a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4
+++ b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4
@@ -9,11 +9,15 @@ options
{
package tonkadur.fate.v1.parser;
+ import java.util.Map;
+ import java.util.HashMap;
+
import tonkadur.error.ErrorManager;
import tonkadur.parser.Context;
import tonkadur.parser.Origin;
+ import tonkadur.fate.v1.error.IllegalReferenceNameException;
import tonkadur.fate.v1.error.UnknownVariableScopeException;
import tonkadur.fate.v1.lang.*;
@@ -55,7 +59,11 @@ general_fate_sequence:
;
first_level_fate_instr:
- DEFINE_SEQUENCE_KW WORD WS+ first_node=general_fate_sequence R_PAREN
+ DEFINE_SEQUENCE_KW
+ new_reference_name
+ WS+
+ first_node=general_fate_sequence
+ R_PAREN
{
/*
world.sequences().add
@@ -65,13 +73,13 @@ first_level_fate_instr:
($DEFINE_SEQUENCE_KW.getLine()),
($DEFINE_SEQUENCE_KW.getCharPositionInLine())
),
- ($WORD.text),
+ ($new_reference_name.result),
//(first_node.result)
);
*/
}
- | DECLARE_VARIABLE_KW scope=WORD WS+ type WS+ name=WORD R_PAREN
+ | DECLARE_VARIABLE_KW scope=WORD WS+ type WS+ name=new_reference_name R_PAREN
{
final Origin start_origin, scope_origin, type_origin;
final Variable new_variable;
@@ -109,13 +117,13 @@ first_level_fate_instr:
start_origin,
variable_scope,
($type.result),
- ($name.text)
+ ($name.result)
);
WORLD.variables().add(new_variable);
}
- | DECLARE_TEXT_EFFECT_KW params=type_list name=WORD R_PAREN
+ | DECLARE_TEXT_EFFECT_KW params=type_list new_reference_name R_PAREN
{
final Origin start_origin;
final TextEffect new_text_effect;
@@ -128,17 +136,22 @@ first_level_fate_instr:
);
new_text_effect =
- new TextEffect(start_origin, ($type_list.result), ($name.text));
+ new TextEffect
+ (
+ start_origin,
+ ($type_list.result),
+ ($new_reference_name.result)
+ );
WORLD.text_effects().add(new_text_effect);
}
- | REQUIRE_EXTENSION_KW name=WORD R_PAREN
+ | REQUIRE_EXTENSION_KW WORD R_PAREN
{
- WORLD.add_required_extension(($name.text));
+ WORLD.add_required_extension(($WORD.text));
}
- | DECLARE_ALIAS_TYPE_KW parent=type WS+ name=WORD R_PAREN
+ | DECLARE_ALIAS_TYPE_KW parent=type WS+ new_reference_name R_PAREN
{
final Origin start_origin;
final Type new_type;
@@ -150,13 +163,50 @@ first_level_fate_instr:
($DECLARE_ALIAS_TYPE_KW.getCharPositionInLine())
);
- new_type = new Type(start_origin, ($parent.result), ($name.text));
+ new_type =
+ new Type
+ (
+ start_origin,
+ ($parent.result),
+ ($new_reference_name.result)
+ );
WORLD.types().add(new_type);
}
- | DECLARE_DICT_TYPE_KW name=WORD typed_param_list R_PAREN
+ | DECLARE_DICT_TYPE_KW new_reference_name WS* typed_entry_list R_PAREN
{
+ final Origin start_origin;
+ final Type new_type;
+ final Map<String, Type> field_types;
+
+ field_types = new HashMap<String, Type>();
+
+ for
+ (
+ final TypedEntryList.TypedEntry te:
+ ($typed_entry_list.result).get_entries()
+ )
+ {
+ field_types.put(te.get_name(), te.get_type());
+ }
+
+ start_origin =
+ CONTEXT.get_origin_at
+ (
+ ($DECLARE_DICT_TYPE_KW.getLine()),
+ ($DECLARE_DICT_TYPE_KW.getCharPositionInLine())
+ );
+
+ new_type =
+ new DictType
+ (
+ start_origin,
+ field_types,
+ ($new_reference_name.result)
+ );
+
+ WORLD.types().add(new_type);
}
| ADD_KW value WS+ value_reference R_PAREN
@@ -171,7 +221,7 @@ first_level_fate_instr:
{
}
- | DECLARE_EVENT_TYPE_KW name=WORD WS+ type_list R_PAREN
+ | DECLARE_EVENT_TYPE_KW new_reference_name WS+ type_list R_PAREN
{
final Origin start_origin;
final Event new_event;
@@ -183,7 +233,13 @@ first_level_fate_instr:
($DECLARE_EVENT_TYPE_KW.getCharPositionInLine())
);
- new_event = new Event(start_origin, ($type_list.result), ($name.text));
+ new_event =
+ new Event
+ (
+ start_origin,
+ ($type_list.result),
+ ($new_reference_name.result)
+ );
WORLD.events().add(new_event);
}
@@ -193,7 +249,8 @@ first_level_fate_instr:
}
| DEFINE_MACRO_KW
- L_PAREN WS+ typed_param_list R_PAREN
+ new_reference_name WS*
+ L_PAREN WS+ typed_entry_list R_PAREN
general_fate_sequence
R_PAREN
{
@@ -357,30 +414,83 @@ type_list
returns [List<Type> result]
@init
{
- final List<Type> result = new ArrayList<Type>();
+ $result = new ArrayList<Type>();
}
:
(
type
{
- result.add(($type.result));
+ $result.add(($type.result));
}
)?
(WS+
type
{
- result.add(($type.result));
+ $result.add(($type.result));
}
)*
{
}
;
-typed_param_list:
- (L_PAREN WORD WS+ type R_PAREN)*
+typed_entry_list
+returns [TypedEntryList result]
+@init
+{
+ $result = new TypedEntryList();
+}
+:
+ (
+ L_PAREN type WS+ new_reference_name R_PAREN
+ {
+ $result.add
+ (
+ CONTEXT.get_origin_at
+ (
+ ($L_PAREN.getLine()),
+ ($L_PAREN.getCharPositionInLine())
+ ),
+ ($type.result),
+ ($new_reference_name.result)
+ );
+ }
+ )*
{
}
;
+catch [final Throwable e]
+{
+ throw new ParseCancellationException(e);
+}
+
+new_reference_name
+returns [String result]
+:
+ WORD
+ {
+ if (($WORD.text).indexOf('.') != -1)
+ {
+ ErrorManager.handle
+ (
+ new IllegalReferenceNameException
+ (
+ CONTEXT.get_origin_at
+ (
+ ($WORD.getLine()),
+ ($WORD.getCharPositionInLine())
+ ),
+ ($WORD.text)
+ )
+ );
+ }
+
+ $result = ($WORD.text);
+ }
+;
+catch [final Throwable e]
+{
+ throw new ParseCancellationException(e);
+}
/******************************************************************************/
/**** VALUES ******************************************************************/