From 9246aeb13007bcb92544b3ef1486552dbf0803ee Mon Sep 17 00:00:00 2001 From: Nathanael Sensfelder Date: Sat, 4 Jul 2020 00:06:25 +0200 Subject: ... --- src/core/src/tonkadur/RuntimeParameters.java | 35 +++++ src/core/src/tonkadur/error/Error.java | 41 ++++++ src/core/src/tonkadur/error/ErrorCategory.java | 28 ++++ src/core/src/tonkadur/error/ErrorLevel.java | 6 + src/core/src/tonkadur/error/ErrorManager.java | 58 ++++++++ .../fate/v1/error/ContextCycleException.java | 47 ------ .../src/tonkadur/fate/v1/error/ErrorCategory.java | 26 ++++ .../src/tonkadur/fate/v1/error/InputException.java | 40 ----- .../v1/error/TypeAlreadyDeclaredException.java | 14 +- src/core/src/tonkadur/fate/v1/lang/Type.java | 128 ++++++++++++++++ src/core/src/tonkadur/fate/v1/lang/World.java | 60 ++++---- src/core/src/tonkadur/fate/v1/parser/Context.java | 126 ---------------- src/core/src/tonkadur/fate/v1/parser/Location.java | 114 -------------- src/core/src/tonkadur/fate/v1/parser/Origin.java | 33 ----- src/core/src/tonkadur/parser/Context.java | 164 +++++++++++++++++++++ .../src/tonkadur/parser/ContextCycleException.java | 53 +++++++ src/core/src/tonkadur/parser/Location.java | 114 ++++++++++++++ src/core/src/tonkadur/parser/Origin.java | 33 +++++ src/core/src/tonkadur/parser/ParsingError.java | 21 +++ 19 files changed, 753 insertions(+), 388 deletions(-) create mode 100644 src/core/src/tonkadur/RuntimeParameters.java create mode 100644 src/core/src/tonkadur/error/Error.java create mode 100644 src/core/src/tonkadur/error/ErrorCategory.java create mode 100644 src/core/src/tonkadur/error/ErrorLevel.java create mode 100644 src/core/src/tonkadur/error/ErrorManager.java delete mode 100644 src/core/src/tonkadur/fate/v1/error/ContextCycleException.java create mode 100644 src/core/src/tonkadur/fate/v1/error/ErrorCategory.java delete mode 100644 src/core/src/tonkadur/fate/v1/error/InputException.java create mode 100644 src/core/src/tonkadur/fate/v1/lang/Type.java delete mode 100644 src/core/src/tonkadur/fate/v1/parser/Context.java delete mode 100644 src/core/src/tonkadur/fate/v1/parser/Location.java delete mode 100644 src/core/src/tonkadur/fate/v1/parser/Origin.java create mode 100644 src/core/src/tonkadur/parser/Context.java create mode 100644 src/core/src/tonkadur/parser/ContextCycleException.java create mode 100644 src/core/src/tonkadur/parser/Location.java create mode 100644 src/core/src/tonkadur/parser/Origin.java create mode 100644 src/core/src/tonkadur/parser/ParsingError.java diff --git a/src/core/src/tonkadur/RuntimeParameters.java b/src/core/src/tonkadur/RuntimeParameters.java new file mode 100644 index 0000000..28a7416 --- /dev/null +++ b/src/core/src/tonkadur/RuntimeParameters.java @@ -0,0 +1,35 @@ +package tonkadur; + +import java.util.Collection; +import java.util.HashSet; + +import tonkadur.error.ErrorCategory; + +public class RuntimeParameters +{ + protected static final Collection disabled_errors; + protected static final Collection tolerated_errors; + protected static boolean consider_warnings_as_errors; + + static + { + disabled_errors = new HashSet(); + tolerated_errors = new HashSet(); + consider_warnings_as_errors = false; + } + + public static boolean error_is_disabled (final ErrorCategory category) + { + return disabled_errors.contains(category); + } + + public static boolean error_is_tolerated (final ErrorCategory category) + { + return tolerated_errors.contains(category); + } + + public static boolean warnings_are_errors () + { + return consider_warnings_as_errors; + } +} diff --git a/src/core/src/tonkadur/error/Error.java b/src/core/src/tonkadur/error/Error.java new file mode 100644 index 0000000..103e428 --- /dev/null +++ b/src/core/src/tonkadur/error/Error.java @@ -0,0 +1,41 @@ +package tonkadur.error; + +public abstract class Error extends Throwable +{ + /***************************************************************************/ + /**** STATIC MEMBERS *******************************************************/ + /***************************************************************************/ + private static final long serialVersionUID = 42L; + + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final ErrorLevel error_level; + protected final ErrorCategory error_category; + + /***************************************************************************/ + /**** PRIVATE **************************************************************/ + /***************************************************************************/ + protected Error + ( + final ErrorLevel error_level, + final ErrorCategory error_category + ) + { + this.error_level = error_level; + this.error_category = error_category; + } + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + public ErrorLevel get_error_level () + { + return error_level; + } + + public ErrorCategory get_error_category () + { + return error_category; + } +} diff --git a/src/core/src/tonkadur/error/ErrorCategory.java b/src/core/src/tonkadur/error/ErrorCategory.java new file mode 100644 index 0000000..122cff3 --- /dev/null +++ b/src/core/src/tonkadur/error/ErrorCategory.java @@ -0,0 +1,28 @@ +package tonkadur.error; + +public class ErrorCategory +{ + public static final ErrorCategory INVALID_INPUT; + public static final ErrorCategory PROGRAMMING_ERROR; + public static final ErrorCategory FILE_ACCESS; + + static + { + INVALID_INPUT = new ErrorCategory("Invalid Input"); + PROGRAMMING_ERROR = new ErrorCategory("Programming Error"); + FILE_ACCESS = new ErrorCategory("File Access"); + } + + protected final String name; + + protected ErrorCategory (final String name) + { + this.name = name; + } + + @Override + public String toString() + { + return name; + } +} diff --git a/src/core/src/tonkadur/error/ErrorLevel.java b/src/core/src/tonkadur/error/ErrorLevel.java new file mode 100644 index 0000000..0cddaae --- /dev/null +++ b/src/core/src/tonkadur/error/ErrorLevel.java @@ -0,0 +1,6 @@ +package tonkadur.error; + +public enum ErrorLevel +{ + WARNING, ERROR, FATAL +} diff --git a/src/core/src/tonkadur/error/ErrorManager.java b/src/core/src/tonkadur/error/ErrorManager.java new file mode 100644 index 0000000..13c9c3f --- /dev/null +++ b/src/core/src/tonkadur/error/ErrorManager.java @@ -0,0 +1,58 @@ +package tonkadur.error; + +import tonkadur.RuntimeParameters; + +public class ErrorManager +{ + /* Utility class */ + private ErrorManager () {}; + + public static + void handle (final CustomError error) + throws CustomError + { + final ErrorCategory error_category; + ErrorLevel error_level; + + error_category = error.get_error_category(); + + if (RuntimeParameters.error_is_disabled(error_category)) + { + return; + } + + error_level = error.get_error_level(); + + if + ( + (error_level == ErrorLevel.WARNING) + && RuntimeParameters.warnings_are_errors() + ) + { + error_level = ErrorLevel.ERROR; + } + + if + ( + (error_level == ErrorLevel.ERROR) + && RuntimeParameters.error_is_tolerated(error_category) + ) + { + error_level = ErrorLevel.WARNING; + } + + switch (error_level) + { + case WARNING: + System.err.println(error.toString()); + break; + + case ERROR: + throw error; + + case FATAL: + System.err.println(error.toString()); + System.exit(-1); + } + } +} diff --git a/src/core/src/tonkadur/fate/v1/error/ContextCycleException.java b/src/core/src/tonkadur/fate/v1/error/ContextCycleException.java deleted file mode 100644 index c5a2434..0000000 --- a/src/core/src/tonkadur/fate/v1/error/ContextCycleException.java +++ /dev/null @@ -1,47 +0,0 @@ -package tonkadur.fate.v1.error; - -import tonkadur.fate.v1.parser.Location; -import tonkadur.fate.v1.parser.Origin; - -public class ContextCycleException extends InputException -{ - /***************************************************************************/ - /**** MEMBERS **************************************************************/ - /***************************************************************************/ - /* - * Using a Location instead of an Origin here, because the file refers to - * something in 'origin' anyway. - */ - protected final Location original_require_location; - protected final String filename; - - /***************************************************************************/ - /**** PUBLIC ***************************************************************/ - /***************************************************************************/ - public ContextCycleException - ( - final Location original_require_location, - final String filename - ) - { - this.original_require_location = original_require_location; - this.filename = filename; - } - - @Override - public String toString () - { - final StringBuilder sb = new StringBuilder(); - - sb.append(origin.get_context().toString()); - sb.append("Cyclic dependency for file '"); - sb.append(filename); - sb.append("' required at "); - sb.append(origin.get_location().toString()); - sb.append(" when it was already required at "); - sb.append(original_require_location.toString()); - sb.append("."); - - return sb.toString(); - } -} diff --git a/src/core/src/tonkadur/fate/v1/error/ErrorCategory.java b/src/core/src/tonkadur/fate/v1/error/ErrorCategory.java new file mode 100644 index 0000000..f56b6d5 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/error/ErrorCategory.java @@ -0,0 +1,26 @@ +package tonkadur.fate.v1.error; + +class ErrorCategory extends tonkadur.error.ErrorCategory +{ + public static final ErrorCategory DUPLICATE_DECLARATION; + public static final ErrorCategory CONFLICTING_DECLARATION; + public static final ErrorCategory UNDECLARED; + public static final ErrorCategory UNKNOWN_SEQUENCE; + public static final ErrorCategory INCORRECT_TYPE; + public static final ErrorCategory INCOMPATIBLE_TYPE; + + static + { + DUPLICATE_DECLARATION = new ErrorCategory("duplicate_declaration"); + CONFLICTING_DECLARATION = new ErrorCategory("conflicting_declaration"); + UNDECLARED = new ErrorCategory("undeclared"); + UNKNOWN_SEQUENCE = new ErrorCategory("unknown_sequence"); + INCORRECT_TYPE = new ErrorCategory("incorrect_type"); + INCOMPATIBLE_TYPE = new ErrorCategory("incompatible_type"); + } + + private ErrorCategory (final String name) + { + super(name); + } +} diff --git a/src/core/src/tonkadur/fate/v1/error/InputException.java b/src/core/src/tonkadur/fate/v1/error/InputException.java deleted file mode 100644 index 71b1878..0000000 --- a/src/core/src/tonkadur/fate/v1/error/InputException.java +++ /dev/null @@ -1,40 +0,0 @@ -package tonkadur.fate.v1.error; - -import tonkadur.fate.v1.parser.Context; -import tonkadur.fate.v1.parser.Origin; - -abstract class InputException extends Throwable -{ - /***************************************************************************/ - /**** STATIC MEMBERS *******************************************************/ - /***************************************************************************/ - private static final long serialVersionUID = 42L; - - /***************************************************************************/ - /**** MEMBERS **************************************************************/ - /***************************************************************************/ - protected Origin origin; - - /***************************************************************************/ - /**** PUBLIC ***************************************************************/ - /***************************************************************************/ - public void set_origin (final Origin origin) - { - this.origin = origin; - } - - public void set_origin - ( - final Context context, - final int line, - final int column - ) - { - origin = context.get_origin_at(line, column); - } - - public Origin get_origin () - { - return origin; - } -} diff --git a/src/core/src/tonkadur/fate/v1/error/TypeAlreadyDeclaredException.java b/src/core/src/tonkadur/fate/v1/error/TypeAlreadyDeclaredException.java index b028127..4050d1e 100644 --- a/src/core/src/tonkadur/fate/v1/error/TypeAlreadyDeclaredException.java +++ b/src/core/src/tonkadur/fate/v1/error/TypeAlreadyDeclaredException.java @@ -1,8 +1,13 @@ package tonkadur.fate.v1.error; +import tonkadur.error.ErrorLevel; + +import tonkadur.parser.Origin; +import tonkadur.parser.ParsingError; + import tonkadur.fate.v1.lang.Type; -public class TypeAlreadyDeclaredException extends InputException +public class TypeAlreadyDeclaredException extends ParsingError { /***************************************************************************/ /**** MEMBERS **************************************************************/ @@ -12,8 +17,13 @@ public class TypeAlreadyDeclaredException extends InputException /***************************************************************************/ /**** PUBLIC ***************************************************************/ /***************************************************************************/ - public TypeAlreadyDeclaredException (final Type original_type) + public TypeAlreadyDeclaredException + ( + final Origin origin, + final Type original_type + ) { + super(ErrorLevel.WARNING, ErrorCategory.DUPLICATE_DECLARATION, origin); this.original_type = original_type; } diff --git a/src/core/src/tonkadur/fate/v1/lang/Type.java b/src/core/src/tonkadur/fate/v1/lang/Type.java new file mode 100644 index 0000000..2990dc0 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/lang/Type.java @@ -0,0 +1,128 @@ +package tonkadur.fate.v1.lang; + +import tonkadur.parser.Origin; + +public class Type +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final Origin origin; + protected final String name; + protected final Type true_type; + protected final Type parent; + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + + /**** Constructors *********************************************************/ + public Type + ( + final Origin origin, + final Type parent, + final String name + ) + { + if (parent == null) + { + true_type = this; + } + else + { + true_type = parent.true_type; + } + + this.origin = origin; + this.parent = parent; + this.name = name; + } + + /**** Accessors ************************************************************/ + public String get_name () + { + return name; + } + + public Origin get_origin () + { + return origin; + } + + public Type get_true_type () + { + return true_type; + } + + public boolean is_base_type () + { + return (parent == null); + } + + /**** Compatibility ********************************************************/ + public boolean can_be_used_as (final Type t) + { + if (!true_type.equals(t.true_type)) + { + return false; + } + + return this_or_parent_equals(t); + } + + /**** Misc. ****************************************************************/ + @Override + public boolean equals (final Object o) + { + if (o instanceof Type) + { + final Type t; + + t = (Type) o; + + return name.equals(t.name); + } + + return false; + } + + @Override + public int hashCode () + { + return name.hashCode(); + } + + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + if (parent != null) + { + sb.append(parent.toString()); + sb.append("::"); + } + + sb.append(name); + + return sb.toString(); + } + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ + protected boolean this_or_parent_equals (final Type t) + { + if (equals(t)) + { + return true; + } + + if (parent == null) + { + return false; + } + + return parent.this_or_parent_equals(t); + } +} diff --git a/src/core/src/tonkadur/fate/v1/lang/World.java b/src/core/src/tonkadur/fate/v1/lang/World.java index fb0f0fe..cd42f55 100644 --- a/src/core/src/tonkadur/fate/v1/lang/World.java +++ b/src/core/src/tonkadur/fate/v1/lang/World.java @@ -11,10 +11,10 @@ public class World /**** MEMBERS **************************************************************/ /***************************************************************************/ protected final Collection loaded_files; - protected final Collection text_effects; protected final Map events; protected final Map macros; protected final Map sequences; + protected final Map text_effects; protected final Map types; protected final Map variables; @@ -26,18 +26,15 @@ public class World public World () { loaded_files = new HashSet(); - text_effects = new HashSet(); events = new HashMap(); macros = new HashMap(); sequences = new HashMap(); + text_effects = new HashMap(); types = new HashMap(); variables = new HashMap(); - for (final Type t: Type.BASE_TYPES) - { - types.add(t.get_name(), t); - } + add_base_types(); } /**** Accessors ************************************************************/ @@ -57,23 +54,6 @@ public class World loaded_files.add(name); } - /**** Text Effects ****/ - public Collection get_text_effects () - { - return text_effects.clone(); - } - - public boolean has_text_effect (final String name) - { - return text_effects.contains(name); - } - - public void add_text_effect (final String name) - throws TextEffectAlreadyDeclaredException - { - text_effects.add(name); - } - /**** Events ****/ public Collection get_events () { @@ -85,15 +65,43 @@ public class World return events.containsKey(name); } - public void add_event (final String name, final List parameter_types) + public void add_event + ( + final Origin origin, + final String name, + final List parameter_types + ) throws EventAlreadyDeclaredException, UnknownTypeException { - + if (has_event(name)) + { + + } + for (final Type t: parameter_types) + { + if (!has_type(t)) + { + throw new UnknownTypeException() + } + } } /**** Misc. ****************************************************************/ /***************************************************************************/ - /**** PRIVATE **************************************************************/ + /**** PROTECTED ************************************************************/ /***************************************************************************/ + protected void add_base_types () + { + final Origin base; + + base = new Origin(new Context(""), Location.BASE_LANGUAGE); + + add_type(base, null, "dict"); + add_type(base, null, "float"); + add_type(base, null, "int"); + add_type(base, null, "list"); + add_type(base, null, "set"); + add_type(base, null, "string"); + } } diff --git a/src/core/src/tonkadur/fate/v1/parser/Context.java b/src/core/src/tonkadur/fate/v1/parser/Context.java deleted file mode 100644 index 3ad958d..0000000 --- a/src/core/src/tonkadur/fate/v1/parser/Context.java +++ /dev/null @@ -1,126 +0,0 @@ -package tonkadur.fate.v1.parser; - -import java.util.Stack; - -import tonkadur.fate.v1.error.ContextCycleException; - -public class Context -{ - /***************************************************************************/ - /**** MEMBERS **************************************************************/ - /***************************************************************************/ - protected final boolean locked; - protected final Stack source; - protected String current_file; - - /***************************************************************************/ - /**** PUBLIC ***************************************************************/ - /***************************************************************************/ - - /**** Constructors *********************************************************/ - public Context (final String filename) - { - locked = false; - source = new Stack(); - current_file = filename; - } - - /**** Accessors ************************************************************/ - public void push (final Location location, final String new_file) - throws ContextCycleException - { - throw_exception_on_cycle(new_file); - - current_file = new_file; - - source.push(location); - } - - public void pop () - { - current_file = source.peek().get_filename(); - source.pop(); - } - - /**** Utils ****************************************************************/ - public Origin get_origin_at (final int line, final int column) - { - return new Origin(this, new Location(current_file, line, column)); - } - - /**** Misc. ****************************************************************/ - @Override - public String toString () - { - final StringBuilder sb = new StringBuilder(); - - /* - * That's in FIFO order, as we want it to be, due to arguable design - * decisions in Java. - */ - for (final Location location: source) - { - sb.append("Require at "); - sb.append(location.toString()); - sb.append(" led to"); - sb.append(System.lineSeparator()); - } - - return sb.toString(); - } - - @Override - public boolean equals (final Object o) - { - if (o instanceof Context) - { - final Context b; - - b = (Context) o; - - return - ( - (source.equals(b.source)) - && (current_file.equals (b.current_file)) - ); - } - - return false; - } - - @Override - public int hashCode () - { - return (source.hashCode() + current_file.hashCode()); - } - - /***************************************************************************/ - /**** PROTECTED ************************************************************/ - /***************************************************************************/ - protected void throw_exception_on_cycle (final String new_file) - throws ContextCycleException - { - Location previous_import; - - previous_import = null; - - /* - * That's in FIFO order, as we want it to be, due to arguable design - * decisions in Java. - */ - for (final Location location: source) - { - if (location.get_filename().equals(new_file)) - { - throw new ContextCycleException(previous_import, new_file); - } - - previous_import = location; - } - - if (current_file.equals(new_file)) - { - throw new ContextCycleException(previous_import, new_file); - } - } -} diff --git a/src/core/src/tonkadur/fate/v1/parser/Location.java b/src/core/src/tonkadur/fate/v1/parser/Location.java deleted file mode 100644 index 98f407d..0000000 --- a/src/core/src/tonkadur/fate/v1/parser/Location.java +++ /dev/null @@ -1,114 +0,0 @@ -package tonkadur.fate.v1.parser; - -public class Location -{ - /***************************************************************************/ - /**** STATIC MEMBERS *******************************************************/ - /***************************************************************************/ - public static final Location BASE_LANGUAGE; - - static - { - BASE_LANGUAGE = new Location(true, "", -1, -1); - } - - /***************************************************************************/ - /**** MEMBERS **************************************************************/ - /***************************************************************************/ - protected final boolean is_base_language; - protected final String filename; - protected final int line; - protected final int column; - - /***************************************************************************/ - /**** PROTECTED ************************************************************/ - /***************************************************************************/ - protected Location - ( - final boolean is_base_language, - final String filename, - final int line, - final int column - ) - { - this.is_base_language = is_base_language; - this.filename = filename; - this.line = line; - this.column = column; - } - - /***************************************************************************/ - /**** PUBLIC ***************************************************************/ - /***************************************************************************/ - - /**** Constructors *********************************************************/ - public Location - ( - final String filename, - final int line, - final int column - ) - { - this.is_base_language = false; - this.filename = filename; - this.line = line; - this.column = column; - } - - /**** Accessors ************************************************************/ - public String get_filename () - { - return filename; - } - - public int get_line () - { - return line; - } - - public int get_column () - { - return line; - } - - /**** Misc. ****************************************************************/ - @Override - public String toString () - { - final StringBuilder sb = new StringBuilder(); - - sb.append(filename); - sb.append(":"); - sb.append(line); - sb.append(","); - sb.append(column); - - return sb.toString(); - } - - @Override - public boolean equals (final Object o) - { - if (o instanceof Location) - { - final Location b; - - b = (Location) o; - - return - ( - (filename.equals(b.filename)) - && (line == b.line) - && (column == b.column) - ); - } - - return false; - } - - @Override - public int hashCode () - { - return (filename.hashCode() + line + column); - } -} diff --git a/src/core/src/tonkadur/fate/v1/parser/Origin.java b/src/core/src/tonkadur/fate/v1/parser/Origin.java deleted file mode 100644 index cd4b784..0000000 --- a/src/core/src/tonkadur/fate/v1/parser/Origin.java +++ /dev/null @@ -1,33 +0,0 @@ -package tonkadur.fate.v1.parser; - -public class Origin -{ - /***************************************************************************/ - /**** MEMBERS **************************************************************/ - /***************************************************************************/ - protected final Context context; - protected final Location location; - - /***************************************************************************/ - /**** PUBLIC ***************************************************************/ - /***************************************************************************/ - public Origin - ( - final Context context, - final Location location - ) - { - this.context = context; - this.location = location; - } - - public Context get_context () - { - return context; - } - - public Location get_location () - { - return location; - } -} diff --git a/src/core/src/tonkadur/parser/Context.java b/src/core/src/tonkadur/parser/Context.java new file mode 100644 index 0000000..f579318 --- /dev/null +++ b/src/core/src/tonkadur/parser/Context.java @@ -0,0 +1,164 @@ +package tonkadur.parser; + +import java.util.Stack; + +public class Context +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final Stack source; + protected String current_file; + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + + /**** Constructors *********************************************************/ + public Context (final String filename) + { + source = new Stack(); + current_file = filename; + } + + /**** Accessors ************************************************************/ + public void push (final Location location, final String new_file) + throws ContextCycleException + { + throw_exception_on_cycle(location, new_file); + + current_file = new_file; + + source.push(location); + } + + public void pop () + { + current_file = source.peek().get_filename(); + source.pop(); + } + + /**** Utils ****************************************************************/ + public Origin get_origin_at (final int line, final int column) + { + return new Origin(clone(), new Location(current_file, line, column)); + } + + public Origin get_origin_at (final Location location) + { + return new Origin(clone(), location); + } + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + /* + * That's in FIFO order, as we want it to be, due to arguable design + * decisions in Java. + */ + for (final Location location: source) + { + sb.append("Require at "); + sb.append(location.toString()); + sb.append(" led to"); + sb.append(System.lineSeparator()); + } + + return sb.toString(); + } + + @Override + public boolean equals (final Object o) + { + if (o instanceof Context) + { + final Context b; + + b = (Context) o; + + return + ( + (source.equals(b.source)) + && (current_file.equals (b.current_file)) + ); + } + + return false; + } + + @Override + public int hashCode () + { + return (source.hashCode() + current_file.hashCode()); + } + + @Override + public Context clone () + { + final Context result; + + result = new Context(""); + + /* + * That's in FIFO order, as we want it to be, due to arguable design + * decisions in Java. + */ + for (final Location location: source) + { + result.source.push(location); + } + + result.current_file = current_file; + + return result; + } + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ + protected void throw_exception_on_cycle + ( + final Location declared_at, + final String new_file + ) + throws ContextCycleException + { + Location previous_import; + + previous_import = null; + + /* + * That's in FIFO order, as we want it to be, due to arguable design + * decisions in Java. + */ + for (final Location location: source) + { + if (location.get_filename().equals(new_file)) + { + throw + new ContextCycleException + ( + get_origin_at(declared_at), + previous_import, + new_file + ); + } + + previous_import = location; + } + + if (current_file.equals(new_file)) + { + throw + new ContextCycleException + ( + get_origin_at(declared_at), + previous_import, + new_file + ); + } + } +} diff --git a/src/core/src/tonkadur/parser/ContextCycleException.java b/src/core/src/tonkadur/parser/ContextCycleException.java new file mode 100644 index 0000000..a7f6314 --- /dev/null +++ b/src/core/src/tonkadur/parser/ContextCycleException.java @@ -0,0 +1,53 @@ +package tonkadur.parser; + +import tonkadur.parser.Location; +import tonkadur.parser.Origin; + +import tonkadur.error.ErrorCategory; +import tonkadur.error.ErrorLevel; + +class ContextCycleException extends ParsingError +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + /* + * Using a Location instead of an Origin here, because the file refers to + * something in 'origin' anyway. + */ + protected final Location original_require_location; + protected final String filename; + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + public ContextCycleException + ( + final Origin origin, + final Location original_require_location, + final String filename + ) + { + super(ErrorLevel.FATAL, ErrorCategory.INVALID_INPUT, origin); + + this.original_require_location = original_require_location; + this.filename = filename; + } + + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append(origin.get_context().toString()); + sb.append("Cyclic dependency for file '"); + sb.append(filename); + sb.append("' required at "); + sb.append(origin.get_location().toString()); + sb.append(" when it was already required at "); + sb.append(original_require_location.toString()); + sb.append("."); + + return sb.toString(); + } +} diff --git a/src/core/src/tonkadur/parser/Location.java b/src/core/src/tonkadur/parser/Location.java new file mode 100644 index 0000000..ea6989b --- /dev/null +++ b/src/core/src/tonkadur/parser/Location.java @@ -0,0 +1,114 @@ +package tonkadur.parser; + +public class Location +{ + /***************************************************************************/ + /**** STATIC MEMBERS *******************************************************/ + /***************************************************************************/ + public static final Location BASE_LANGUAGE; + + static + { + BASE_LANGUAGE = new Location(true, "", -1, -1); + } + + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final boolean is_base_language; + protected final String filename; + protected final int line; + protected final int column; + + /***************************************************************************/ + /**** PROTECTED ************************************************************/ + /***************************************************************************/ + protected Location + ( + final boolean is_base_language, + final String filename, + final int line, + final int column + ) + { + this.is_base_language = is_base_language; + this.filename = filename; + this.line = line; + this.column = column; + } + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + + /**** Constructors *********************************************************/ + public Location + ( + final String filename, + final int line, + final int column + ) + { + this.is_base_language = false; + this.filename = filename; + this.line = line; + this.column = column; + } + + /**** Accessors ************************************************************/ + public String get_filename () + { + return filename; + } + + public int get_line () + { + return line; + } + + public int get_column () + { + return line; + } + + /**** Misc. ****************************************************************/ + @Override + public String toString () + { + final StringBuilder sb = new StringBuilder(); + + sb.append(filename); + sb.append(":"); + sb.append(line); + sb.append(","); + sb.append(column); + + return sb.toString(); + } + + @Override + public boolean equals (final Object o) + { + if (o instanceof Location) + { + final Location b; + + b = (Location) o; + + return + ( + (filename.equals(b.filename)) + && (line == b.line) + && (column == b.column) + ); + } + + return false; + } + + @Override + public int hashCode () + { + return (filename.hashCode() + line + column); + } +} diff --git a/src/core/src/tonkadur/parser/Origin.java b/src/core/src/tonkadur/parser/Origin.java new file mode 100644 index 0000000..9fa7939 --- /dev/null +++ b/src/core/src/tonkadur/parser/Origin.java @@ -0,0 +1,33 @@ +package tonkadur.parser; + +public class Origin +{ + /***************************************************************************/ + /**** MEMBERS **************************************************************/ + /***************************************************************************/ + protected final Context context; + protected final Location location; + + /***************************************************************************/ + /**** PUBLIC ***************************************************************/ + /***************************************************************************/ + public Origin + ( + final Context context, + final Location location + ) + { + this.context = context; + this.location = location; + } + + public Context get_context () + { + return context; + } + + public Location get_location () + { + return location; + } +} diff --git a/src/core/src/tonkadur/parser/ParsingError.java b/src/core/src/tonkadur/parser/ParsingError.java new file mode 100644 index 0000000..5d8bbe5 --- /dev/null +++ b/src/core/src/tonkadur/parser/ParsingError.java @@ -0,0 +1,21 @@ +package tonkadur.parser; + +import tonkadur.error.Error; +import tonkadur.error.ErrorCategory; +import tonkadur.error.ErrorLevel; + +public abstract class ParsingError extends Error +{ + protected final Origin origin; + + protected ParsingError + ( + final ErrorLevel error_level, + final ErrorCategory error_category, + final Origin origin + ) + { + super(error_level, error_category); + this.origin = origin; + } +} -- cgit v1.2.3-70-g09d2