| summaryrefslogtreecommitdiff | 
diff options
Diffstat (limited to 'src/core')
| -rw-r--r-- | src/core/Makefile | 6 | ||||
| -rw-r--r-- | src/core/src/tonkadur/fate/v1/error/ContextCycleException.java | 47 | ||||
| -rw-r--r-- | src/core/src/tonkadur/fate/v1/error/InputException.java | 40 | ||||
| -rw-r--r-- | src/core/src/tonkadur/fate/v1/error/TypeAlreadyDeclaredException.java | 10 | ||||
| -rw-r--r-- | src/core/src/tonkadur/fate/v1/parser/Context.java | 126 | ||||
| -rw-r--r-- | src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 | 5 | ||||
| -rw-r--r-- | src/core/src/tonkadur/fate/v1/parser/FateParser.g4 | 64 | ||||
| -rw-r--r-- | src/core/src/tonkadur/fate/v1/parser/Location.java | 114 | ||||
| -rw-r--r-- | src/core/src/tonkadur/fate/v1/parser/Origin.java | 33 | 
9 files changed, 401 insertions, 44 deletions
| diff --git a/src/core/Makefile b/src/core/Makefile index 178f01b..ffca63b 100644 --- a/src/core/Makefile +++ b/src/core/Makefile @@ -80,11 +80,9 @@ clean:  	rm -rf $(BIN_DIR)/*  	rm -rf $(TARGET) $(STANDALONE) -$(SRC_DIR)/tonkadur/parser/LangParser.java: $(ANTLR_SOURCES) -  # Pattern rules can be used to generate multiple target in a single action. -LangLexer%java LangParser%java: $(ANTLR_SOURCES) -	$(JAVA) -jar $(ANTLR_JAR) -lib $(SRC_DIR)/tonkadur/parser/ $^ +%Lexer.java %Parser.java: $(ANTLR_SOURCES) +	$(JAVA) -jar $(ANTLR_JAR) -lib $(dir $@) $^  $(CLASSES): $(BIN_DIR)/%.class: $(SRC_DIR)/%.java $(BIN_DIR)  	$(JAVAC) -cp $(CLASSPATH) -d $(BIN_DIR) $< diff --git a/src/core/src/tonkadur/fate/v1/error/ContextCycleException.java b/src/core/src/tonkadur/fate/v1/error/ContextCycleException.java new file mode 100644 index 0000000..c5a2434 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/error/ContextCycleException.java @@ -0,0 +1,47 @@ +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/InputException.java b/src/core/src/tonkadur/fate/v1/error/InputException.java index d2921cb..71b1878 100644 --- a/src/core/src/tonkadur/fate/v1/error/InputException.java +++ b/src/core/src/tonkadur/fate/v1/error/InputException.java @@ -1,5 +1,8 @@  package tonkadur.fate.v1.error; +import tonkadur.fate.v1.parser.Context; +import tonkadur.fate.v1.parser.Origin; +  abstract class InputException extends Throwable  {     /***************************************************************************/ @@ -10,43 +13,28 @@ abstract class InputException extends Throwable     /***************************************************************************/     /**** MEMBERS **************************************************************/     /***************************************************************************/ -   protected String filename = ""; -   protected int line = -1; -   protected int column = -1; +   protected Origin origin;     /***************************************************************************/     /**** PUBLIC ***************************************************************/     /***************************************************************************/ -   public InputException set_location +   public void set_origin (final Origin origin) +   { +      this.origin = origin; +   } + +   public void set_origin     ( -      final String filename, +      final Context context,        final int line,        final int column     )     { -      this.filename = filename; -      this.line = line; -      this.column = column; - -      return this; -   } - -   public String get_location () -   { -      final StringBuilder sb = new StringBuilder(); - -      sb.append(filename); -      sb.append(":"); -      sb.append(line); -      sb.append(","); -      sb.append(column); - -      return sb.toString(); +      origin = context.get_origin_at(line, column);     } -   @Override -   public String toString () +   public Origin get_origin ()     { -      return get_location(); +      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 673a3bd..b028127 100644 --- a/src/core/src/tonkadur/fate/v1/error/TypeAlreadyDeclaredException.java +++ b/src/core/src/tonkadur/fate/v1/error/TypeAlreadyDeclaredException.java @@ -22,11 +22,13 @@ public class TypeAlreadyDeclaredException extends InputException     {        final StringBuilder sb = new StringBuilder(); -      sb.append(super.toString()); -      sb.append(" Type '"); +      sb.append(origin.get_context().toString()); +      sb.append("Declaration for type '");        sb.append(original_type.get_name()); -      sb.append("' already declared in "); -      sb.append(original_type.get_source().toString()); +      sb.append("' at "); +      sb.append(origin.get_location().toString()); +      sb.append(" when it was already declared at "); +      sb.append(original_type.get_origin().get_location().toString());        sb.append(".");        return sb.toString(); diff --git a/src/core/src/tonkadur/fate/v1/parser/Context.java b/src/core/src/tonkadur/fate/v1/parser/Context.java new file mode 100644 index 0000000..3ad958d --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/parser/Context.java @@ -0,0 +1,126 @@ +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<Location> source; +   protected String current_file; + +   /***************************************************************************/ +   /**** PUBLIC ***************************************************************/ +   /***************************************************************************/ + +   /**** Constructors *********************************************************/ +   public Context (final String filename) +   { +      locked = false; +      source = new Stack<Location>(); +      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/FateLexer.g4 b/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 index 80fe1fd..3671a4f 100644 --- a/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 +++ b/src/core/src/tonkadur/fate/v1/parser/FateLexer.g4 @@ -5,8 +5,6 @@ lexer grammar FateLexer;     package tonkadur.fate.v1.parser;  } - -  fragment SEP: [ \t\r\n]+;  WS: SEP; @@ -53,6 +51,9 @@ PARAMETER_KW: L_PAREN 'parameter' WS*;  PLUS_KW: L_PAREN 'plus' WS*;  POWER_KW: L_PAREN 'power' WS*;  RANDOM_KW: L_PAREN 'random' WS*; +DECLARE_TEXT_EFFECT_KW: L_PAREN 'declare_text_effect' WS*; +PLAYER_CHOICE_KW: L_PAREN 'player_choice' WS*; +CAST_KW: L_PAREN 'cast' WS*;  REMOVE_ALL_KW: L_PAREN 'remove_all' WS*;  REMOVE_ONE_KW: L_PAREN 'remove_one' WS*;  REQUIRE_KW: L_PAREN 'require' WS*; diff --git a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 index c0be842..408d71d 100644 --- a/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 +++ b/src/core/src/tonkadur/fate/v1/parser/FateParser.g4 @@ -123,25 +123,67 @@ general_fate_instr:     {     } -   | NEWLINE_KW +   | IF_ELSE_KW value WS+ general_fate_instr WS+ general_fate_instr R_PAREN +   { +   } + +   | COND_KW instr_cond_list R_PAREN +   { +   } + +   | PLAYER_CHOICE_KW player_choice* R_PAREN +   { +   } + +   | text+ +   { +   } +; + +instr_cond_list: +   (L_PAREN value WS+ general_fate_instr R_PAREN)+ +   { +   } +; + +player_choice: +   L_PAREN L_PAREN text+ R_PAREN WS+ general_fate_instr R_PAREN +   { +   } + +   | IF_KW value WS+ player_choice R_PAREN +   { +   } + +   | IF_ELSE_KW value WS+ player_choice WS+ player_choice R_PAREN     {     } -   | text +   | COND_KW player_choice_cond_list R_PAREN +   { +   } +; + +player_choice_cond_list: +   (L_PAREN value WS+ player_choice R_PAREN)+     {     }  ;  text: -   sentence text* +   sentence     {     } -   | (ENABLE_TEXT_PARAMETER_KW WORD WS+ text R_PAREN) text* +   | ENABLE_TEXT_PARAMETER_KW WORD WS+ text+ R_PAREN     {     } -   | non_text_value text* +   | NEWLINE_KW +   { +   } + +   | non_text_value     {     }  ; @@ -289,7 +331,7 @@ value:  ;  non_text_value: -   | IF_ELSE_KW value WS+ value WS+ value R_PAREN +   IF_ELSE_KW value WS+ value WS+ value R_PAREN     {     } @@ -305,6 +347,10 @@ non_text_value:     {     } +   | CAST_KW WORD WORD value R_PAREN +   { +   } +     | value_reference     {     } @@ -325,13 +371,15 @@ value_reference:  ;  value_cond_list: -   (L_PAREN value WS value R_PAREN)+ +   (L_PAREN value WS+ value R_PAREN)+     {     }  ;  value_list: -   value* +   value* (WS+ value)*     {     }  ; + + diff --git a/src/core/src/tonkadur/fate/v1/parser/Location.java b/src/core/src/tonkadur/fate/v1/parser/Location.java new file mode 100644 index 0000000..98f407d --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/parser/Location.java @@ -0,0 +1,114 @@ +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 new file mode 100644 index 0000000..cd4b784 --- /dev/null +++ b/src/core/src/tonkadur/fate/v1/parser/Origin.java @@ -0,0 +1,33 @@ +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; +   } +} | 


