From bb22ba649662258368b86cbe7a0ef2b830f75c84 Mon Sep 17 00:00:00 2001 From: Nathanael Sensfelder Date: Sat, 18 Jul 2020 15:45:21 +0200 Subject: Adds file path management. --- data/examples/the_thief/include/chapters.fate | 2 + data/examples/the_thief/include/characters.fate | 2 +- data/examples/the_thief/include/text_effects.fate | 3 + .../examples/the_thief/include/type/character.fate | 4 +- src/core/src/tonkadur/Files.java | 55 ++++++++++++++++ src/core/src/tonkadur/Main.java | 4 +- src/core/src/tonkadur/RuntimeParameters.java | 14 +++++ src/core/src/tonkadur/fate/v1/Utils.java | 3 +- src/core/src/tonkadur/fate/v1/lang/Event.java | 2 +- src/core/src/tonkadur/fate/v1/lang/TextEffect.java | 2 +- src/core/src/tonkadur/fate/v1/lang/Variable.java | 2 +- src/core/src/tonkadur/fate/v1/lang/type/Type.java | 2 +- src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 | 2 +- src/core/src/tonkadur/fate/v1/parser/FateParser.g4 | 41 +++++++----- src/core/src/tonkadur/parser/Context.java | 73 ++++++++++++++++++---- src/core/src/tonkadur/parser/Location.java | 14 ++++- src/core/src/tonkadur/parser/Origin.java | 7 +++ 17 files changed, 195 insertions(+), 37 deletions(-) create mode 100644 data/examples/the_thief/include/chapters.fate create mode 100644 data/examples/the_thief/include/text_effects.fate create mode 100644 src/core/src/tonkadur/Files.java diff --git a/data/examples/the_thief/include/chapters.fate b/data/examples/the_thief/include/chapters.fate new file mode 100644 index 0000000..d7beb18 --- /dev/null +++ b/data/examples/the_thief/include/chapters.fate @@ -0,0 +1,2 @@ +(fate_version 1) + diff --git a/data/examples/the_thief/include/characters.fate b/data/examples/the_thief/include/characters.fate index 4c36a8e..386d0de 100644 --- a/data/examples/the_thief/include/characters.fate +++ b/data/examples/the_thief/include/characters.fate @@ -1,6 +1,6 @@ (fate_version 1) -(require include/type/character.fate) +(require type/character.fate) (declare_variable local character oscar) (declare_variable local character carla) diff --git a/data/examples/the_thief/include/text_effects.fate b/data/examples/the_thief/include/text_effects.fate new file mode 100644 index 0000000..c8cdd7e --- /dev/null +++ b/data/examples/the_thief/include/text_effects.fate @@ -0,0 +1,3 @@ +(fate_version 1) + +(declare_text_effect narrator) diff --git a/data/examples/the_thief/include/type/character.fate b/data/examples/the_thief/include/type/character.fate index e3b1b7b..5882fd5 100644 --- a/data/examples/the_thief/include/type/character.fate +++ b/data/examples/the_thief/include/type/character.fate @@ -1,7 +1,7 @@ (fate_version 1) -(require include/type/stat.fate) -(require include/type/location.fate) +(require stat.fate) +(require location.fate) (declare_dict_type character (string name) diff --git a/src/core/src/tonkadur/Files.java b/src/core/src/tonkadur/Files.java new file mode 100644 index 0000000..4673af4 --- /dev/null +++ b/src/core/src/tonkadur/Files.java @@ -0,0 +1,55 @@ +package tonkadur; + +import java.nio.file.Path; +import java.nio.file.Paths; + +import tonkadur.parser.Context; + +public class Files +{ + /* Utility class. */ + private Files () {} + + public static String prepare_filename + ( + final String filename + ) + { + return Paths.get(filename).toAbsolutePath().normalize().toString(); + } + + public static String resolve_filename + ( + final Context context, + final String name + ) + { + Path candidate; + + candidate = Paths.get(context.get_current_directory().toString(), name); + + if (java.nio.file.Files.exists(candidate)) + { + return candidate.toAbsolutePath().normalize().toString(); + } + + for (final String dir: RuntimeParameters.get_include_directories()) + { + candidate = Paths.get(dir, name); + + if (java.nio.file.Files.exists(candidate)) + { + return candidate.toAbsolutePath().normalize().toString(); + } + } + + candidate = Paths.get(name); + + if (java.nio.file.Files.exists(candidate)) + { + return candidate.toAbsolutePath().normalize().toString(); + } + + return name; + } +} diff --git a/src/core/src/tonkadur/Main.java b/src/core/src/tonkadur/Main.java index 382dab6..21bc077 100644 --- a/src/core/src/tonkadur/Main.java +++ b/src/core/src/tonkadur/Main.java @@ -20,9 +20,9 @@ public class Main final Context context; world = new World(); - context = new Context(args[0]); + context = Context.build(args[0]); - Utils.add_file_content(args[0], context, world); + Utils.add_file_content(context.get_current_file(), context, world); System.out.println("Parsing completed."); System.out.println(world.toString()); diff --git a/src/core/src/tonkadur/RuntimeParameters.java b/src/core/src/tonkadur/RuntimeParameters.java index 28a7416..2c434d2 100644 --- a/src/core/src/tonkadur/RuntimeParameters.java +++ b/src/core/src/tonkadur/RuntimeParameters.java @@ -1,18 +1,22 @@ package tonkadur; +import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; +import java.util.List; import tonkadur.error.ErrorCategory; public class RuntimeParameters { + protected static final List include_directories; protected static final Collection disabled_errors; protected static final Collection tolerated_errors; protected static boolean consider_warnings_as_errors; static { + include_directories = new ArrayList(); disabled_errors = new HashSet(); tolerated_errors = new HashSet(); consider_warnings_as_errors = false; @@ -32,4 +36,14 @@ public class RuntimeParameters { return consider_warnings_as_errors; } + + public static List get_include_directories () + { + return include_directories; + } + + public static void add_include_directory (final String name) + { + include_directories.add(name); + } } diff --git a/src/core/src/tonkadur/fate/v1/Utils.java b/src/core/src/tonkadur/fate/v1/Utils.java index 1049e0d..7cac057 100644 --- a/src/core/src/tonkadur/fate/v1/Utils.java +++ b/src/core/src/tonkadur/fate/v1/Utils.java @@ -39,7 +39,8 @@ public class Utils if (parser.getNumberOfSyntaxErrors() > 0) { - throw new IOException("There were syntaxic errors in" + filename); + throw new IOException("There were syntaxic errors in " + filename); } } + } diff --git a/src/core/src/tonkadur/fate/v1/lang/Event.java b/src/core/src/tonkadur/fate/v1/lang/Event.java index 55b8c62..7b914b8 100644 --- a/src/core/src/tonkadur/fate/v1/lang/Event.java +++ b/src/core/src/tonkadur/fate/v1/lang/Event.java @@ -22,7 +22,7 @@ public class Event extends DeclaredEntity ANY = new Event ( - new Origin(new Context(""), Location.BASE_LANGUAGE), + Origin.BASE_LANGUAGE, new ArrayList(), /* * Use of a space necessary to avoid conflicting with a user created diff --git a/src/core/src/tonkadur/fate/v1/lang/TextEffect.java b/src/core/src/tonkadur/fate/v1/lang/TextEffect.java index dde0cfd..f833027 100644 --- a/src/core/src/tonkadur/fate/v1/lang/TextEffect.java +++ b/src/core/src/tonkadur/fate/v1/lang/TextEffect.java @@ -22,7 +22,7 @@ public class TextEffect extends Event ANY = new TextEffect ( - new Origin(new Context(""), Location.BASE_LANGUAGE), + Origin.BASE_LANGUAGE, new ArrayList(), /* * Use of a space necessary to avoid conflicting with a user created diff --git a/src/core/src/tonkadur/fate/v1/lang/Variable.java b/src/core/src/tonkadur/fate/v1/lang/Variable.java index 0b6bba5..dfd6c04 100644 --- a/src/core/src/tonkadur/fate/v1/lang/Variable.java +++ b/src/core/src/tonkadur/fate/v1/lang/Variable.java @@ -22,7 +22,7 @@ public class Variable extends DeclaredEntity ANY = new Variable ( - new Origin(new Context(""), Location.BASE_LANGUAGE), + Origin.BASE_LANGUAGE, VariableScope.ANY, Type.ANY, /* diff --git a/src/core/src/tonkadur/fate/v1/lang/type/Type.java b/src/core/src/tonkadur/fate/v1/lang/type/Type.java index 4d3ad1d..87ef5fe 100644 --- a/src/core/src/tonkadur/fate/v1/lang/type/Type.java +++ b/src/core/src/tonkadur/fate/v1/lang/type/Type.java @@ -37,7 +37,7 @@ public class Type extends DeclaredEntity { final Origin base; - base = new Origin(new Context(""), Location.BASE_LANGUAGE); + base = Origin.BASE_LANGUAGE; /* * Use of a space necessary to avoid conflicting with a user created type. diff --git a/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 b/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 index f8fe10f..3654a30 100644 --- a/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 +++ b/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 @@ -31,7 +31,7 @@ DECLARE_VARIABLE_KW: L_PAREN 'declare_variable'; DEFINE_MACRO_KW: L_PAREN 'define_macro'; DEFINE_SEQUENCE_KW: L_PAREN 'define_sequence'; DIVIDE_KW: L_PAREN ('divide'|'/'); -ENABLE_TEXT_PARAMETER_KW: L_PAREN 'enable_text_parameter'; +ENABLE_TEXT_PARAMETER_KW: L_PAREN 'text_effect'; EQUALS_KW: L_PAREN ('equals'|'='|'=='); EVENT_KW: L_PAREN 'event'; EXTENSION_FIRST_LEVEL_KW: L_PAREN '@'; diff --git a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 index bcda80d..4d111f5 100644 --- a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 +++ b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 @@ -13,6 +13,7 @@ options import java.util.Map; import java.util.HashMap; + import tonkadur.Files; import tonkadur.error.ErrorManager; @@ -77,7 +78,6 @@ returns [List result] } WS*)* { - /* TODO */ } ; @@ -371,20 +371,23 @@ first_level_fate_instr: | REQUIRE_KW WS+ WORD WS* R_PAREN { - if (!WORLD.has_loaded_file(($WORD.text))) + final String filename; + + filename = Files.resolve_filename(CONTEXT, ($WORD.text)); + + if (!WORLD.has_loaded_file(filename)) { CONTEXT.push ( - new Location + CONTEXT.get_location_at ( - CONTEXT.get_current_file(), ($REQUIRE_KW.getLine()), ($REQUIRE_KW.getCharPositionInLine()) ), - ($WORD.text) + filename ); - Utils.add_file_content(($WORD.text), CONTEXT, WORLD); + Utils.add_file_content(filename, CONTEXT, WORLD); CONTEXT.pop(); } @@ -392,18 +395,21 @@ first_level_fate_instr: | INCLUDE_KW WS+ WORD WS* R_PAREN { + final String filename; + + filename = Files.resolve_filename(CONTEXT, ($WORD.text)); + CONTEXT.push ( - new Location + CONTEXT.get_location_at ( - CONTEXT.get_current_file(), ($INCLUDE_KW.getLine()), ($INCLUDE_KW.getCharPositionInLine()) ), - ($WORD.text) + filename ); - Utils.add_file_content(($WORD.text), CONTEXT, WORLD); + Utils.add_file_content(filename, CONTEXT, WORLD); CONTEXT.pop(); } @@ -440,8 +446,6 @@ returns [InstructionNode result] : L_PAREN WS+ general_fate_sequence WS* R_PAREN { - /* TODO */ - $result = new InstructionList ( @@ -1043,8 +1047,17 @@ returns [ValueNode result]: | IS_MEMBER_KW WS+ value WS+ value_reference WS* R_PAREN { - /* TODO */ - $result = null; + $result = + IsMemberOperator.build + ( + CONTEXT.get_origin_at + ( + ($IS_MEMBER_KW.getLine()), + ($IS_MEMBER_KW.getCharPositionInLine()) + ), + ($value.result), + ($value_reference.result) + ); } ; catch [final Throwable e] diff --git a/src/core/src/tonkadur/parser/Context.java b/src/core/src/tonkadur/parser/Context.java index c3278ff..edb1e68 100644 --- a/src/core/src/tonkadur/parser/Context.java +++ b/src/core/src/tonkadur/parser/Context.java @@ -1,41 +1,64 @@ package tonkadur.parser; +import java.nio.file.Path; +import java.nio.file.Paths; + +import java.io.IOException; + import java.util.Stack; public class Context { + public static Context BASE_LANGUAGE; + + static + { + BASE_LANGUAGE = new Context(null, ""); + } + /***************************************************************************/ /**** MEMBERS **************************************************************/ /***************************************************************************/ protected final Stack source; + protected Path current_directory; protected String current_file; /***************************************************************************/ /**** PUBLIC ***************************************************************/ /***************************************************************************/ - /**** Constructors *********************************************************/ - public Context (final String filename) + public static Context build (String filename) { - source = new Stack(); - current_file = filename; + Path current_directory; + + current_directory = Paths.get(filename).toAbsolutePath().normalize(); + filename = current_directory.toString(); + current_directory = current_directory.getParent(); + + return new Context(current_directory, filename); } /**** Accessors ************************************************************/ public void push (final Location location, final String new_file) - throws ContextCycleException + throws + ContextCycleException { throw_exception_on_cycle(location, new_file); current_file = new_file; + current_directory = Paths.get(new_file).getParent(); source.push(location); } public void pop () { - current_file = source.peek().get_filename(); - source.pop(); + final Location previous_location; + + previous_location = source.pop(); + + current_file = previous_location.get_filename(); + current_directory = previous_location.get_directory(); } public String get_current_file () @@ -43,10 +66,31 @@ public class Context return current_file; } + public Path get_current_directory () + { + return current_directory; + } + /**** Utils ****************************************************************/ public Origin get_origin_at (final int line, final int column) { - return new Origin(clone(), new Location(current_file, line, column)); + return + new Origin + ( + clone(), + new Location + ( + current_directory, + current_file, + line, + column + ) + ); + } + + public Location get_location_at (final int line, final int column) + { + return new Location(current_directory, current_file, line, column); } public Origin get_origin_at (final Location location) @@ -105,7 +149,7 @@ public class Context { final Context result; - result = new Context(""); + result = new Context(current_directory, current_file); /* * That's in FIFO order, as we want it to be, due to arguable design @@ -116,14 +160,21 @@ public class Context result.source.push(location); } - result.current_file = current_file; - return result; } /***************************************************************************/ /**** PROTECTED ************************************************************/ /***************************************************************************/ + /**** Constructors *********************************************************/ + protected Context (final Path directory, final String filename) + { + source = new Stack(); + current_file = filename; + current_directory = directory; + } + + /**** Utils ****************************************************************/ protected void throw_exception_on_cycle ( final Location declared_at, diff --git a/src/core/src/tonkadur/parser/Location.java b/src/core/src/tonkadur/parser/Location.java index ea6989b..8e86a95 100644 --- a/src/core/src/tonkadur/parser/Location.java +++ b/src/core/src/tonkadur/parser/Location.java @@ -1,5 +1,7 @@ package tonkadur.parser; +import java.nio.file.Path; + public class Location { /***************************************************************************/ @@ -9,7 +11,7 @@ public class Location static { - BASE_LANGUAGE = new Location(true, "", -1, -1); + BASE_LANGUAGE = new Location(true, null, "", -1, -1); } /***************************************************************************/ @@ -17,6 +19,7 @@ public class Location /***************************************************************************/ protected final boolean is_base_language; protected final String filename; + protected final Path directory; protected final int line; protected final int column; @@ -26,12 +29,14 @@ public class Location protected Location ( final boolean is_base_language, + final Path directory, final String filename, final int line, final int column ) { this.is_base_language = is_base_language; + this.directory = directory; this.filename = filename; this.line = line; this.column = column; @@ -44,18 +49,25 @@ public class Location /**** Constructors *********************************************************/ public Location ( + final Path directory, final String filename, final int line, final int column ) { this.is_base_language = false; + this.directory = directory; this.filename = filename; this.line = line; this.column = column; } /**** Accessors ************************************************************/ + public Path get_directory () + { + return directory; + } + public String get_filename () { return filename; diff --git a/src/core/src/tonkadur/parser/Origin.java b/src/core/src/tonkadur/parser/Origin.java index f6f2d29..9d41fac 100644 --- a/src/core/src/tonkadur/parser/Origin.java +++ b/src/core/src/tonkadur/parser/Origin.java @@ -2,6 +2,13 @@ package tonkadur.parser; public class Origin { + public static final Origin BASE_LANGUAGE; + + static + { + BASE_LANGUAGE = new Origin(Context.BASE_LANGUAGE, Location.BASE_LANGUAGE); + } + /***************************************************************************/ /**** MEMBERS **************************************************************/ /***************************************************************************/ -- cgit v1.2.3-70-g09d2