Ada: step1 with opentoken
authorChris M Moore <zmower@ntlworld.com>
Sun, 15 Mar 2015 19:56:09 +0000 (19:56 +0000)
committerChris M Moore <zmower@ntlworld.com>
Sun, 15 Mar 2015 20:08:07 +0000 (20:08 +0000)
12 files changed:
ada/Makefile
ada/opentoken-recognizer-single_character_set.adb [new file with mode: 0644]
ada/opentoken-recognizer-single_character_set.ads [new file with mode: 0644]
ada/printer.adb [new file with mode: 0644]
ada/printer.ads [new file with mode: 0644]
ada/reader.adb [new file with mode: 0644]
ada/reader.ads [new file with mode: 0644]
ada/step0_repl.gpr [new file with mode: 0644]
ada/step1_read_print.adb [new file with mode: 0644]
ada/step1_read_print.gpr [new file with mode: 0644]
ada/types.adb [new file with mode: 0644]
ada/types.ads [new file with mode: 0644]

index 73fdd99..6ba2859 100644 (file)
@@ -1,8 +1,12 @@
-all:   step0_repl
+all:   step0_repl step1_read_print
 
 
 step0_repl:    step0_repl.adb
-       gnatmake -f -g -o $@ $<
+       gnatmake -g -P$@
+
+step1_read_print:      step1_read_print.adb types.ad[bs] reader.ad[bs] \
+                       printer.ad[bs]
+       gnatmake -g -P$@
 
 clean:
-       rm -f b~* *.o *.ali step0_repl
+       rm -f obj/* step0_repl step1_read_print
diff --git a/ada/opentoken-recognizer-single_character_set.adb b/ada/opentoken-recognizer-single_character_set.adb
new file mode 100644 (file)
index 0000000..0678754
--- /dev/null
@@ -0,0 +1,75 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 1999 FlightSafety International and Ted Dennison
+--
+-- This file is part of the OpenToken package.
+--
+-- The OpenToken package is free software; you can redistribute it and/or
+-- modify it under the terms of the  GNU General Public License as published
+-- by the Free Software Foundation; either version 3, or (at your option)
+-- any later version. The OpenToken package is distributed in the hope that
+-- it will be useful, but WITHOUT ANY WARRANTY; without even the implied
+-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for  more details.  You should have received
+-- a copy of the GNU General Public License  distributed with the OpenToken
+-- package;  see file GPL.txt.  If not, write to  the Free Software Foundation,
+-- 59 Temple Place - Suite 330,  Boston, MA 02111-1307, USA.
+--
+--  As a special exception, if other files instantiate generics from
+--  this unit, or you link this unit with other files to produce an
+--  executable, this unit does not by itself cause the resulting
+--  executable to be covered by the GNU General Public License. This
+--  exception does not however invalidate any other reasons why the
+--  executable file might be covered by the GNU Public License.
+--
+--  This software was originally developed by the following company, and was
+--  released as open-source software as a service to the community:
+--
+--           FlightSafety International Simulation Systems Division
+--                    Broken Arrow, OK  USA  918-259-4000
+--
+-------------------------------------------------------------------------------
+
+-----------------------------------------------------------------------------
+--  This package implements a token recognizer for a token of a
+--  single characters from a given set.
+-----------------------------------------------------------------------------
+package body OpenToken.Recognizer.Single_Character_Set is
+
+   overriding procedure Clear (The_Token : in out Instance)
+   is begin
+      The_Token.State := First_Char;
+   end Clear;
+
+   overriding procedure Analyze
+     (The_Token : in out Instance;
+      Next_Char : in     Character;
+      Verdict   :    out Analysis_Verdict)
+   is begin
+      case The_Token.State is
+      when First_Char =>
+         if Ada.Strings.Maps.Is_In (Element => Next_Char, Set => The_Token.Set) then
+            Verdict := Matches;
+            The_Token.State := Done;
+         else
+            Verdict         := Failed;
+            The_Token.State := Done;
+         end if;
+      when Done =>
+         --  We shouldn't get called from here.
+         Verdict := Failed;
+      end case;
+   end Analyze;
+
+   ----------------------------------------------------------------------------
+   --  This procedure will be called to create a character set token
+   ----------------------------------------------------------------------------
+   function Get (Set        : in Ada.Strings.Maps.Character_Set)
+                return Instance
+   is begin
+      return (Report => True,
+              State  => First_Char,
+              Set    => Set);
+   end Get;
+
+end OpenToken.Recognizer.Single_Character_Set;
diff --git a/ada/opentoken-recognizer-single_character_set.ads b/ada/opentoken-recognizer-single_character_set.ads
new file mode 100644 (file)
index 0000000..fabf4fd
--- /dev/null
@@ -0,0 +1,76 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 1999 FlightSafety International and Ted Dennison
+--
+-- This file is part of the OpenToken package.
+--
+-- The OpenToken package is free software; you can redistribute it and/or
+-- modify it under the terms of the  GNU General Public License as published
+-- by the Free Software Foundation; either version 3, or (at your option)
+-- any later version. The OpenToken package is distributed in the hope that
+-- it will be useful, but WITHOUT ANY WARRANTY; without even the implied
+-- warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for  more details.  You should have received
+-- a copy of the GNU General Public License  distributed with the OpenToken
+-- package;  see file GPL.txt.  If not, write to  the Free Software Foundation,
+-- 59 Temple Place - Suite 330,  Boston, MA 02111-1307, USA.
+--
+--  As a special exception, if other files instantiate generics from
+--  this unit, or you link this unit with other files to produce an
+--  executable, this unit does not by itself cause the resulting
+--  executable to be covered by the GNU General Public License. This
+--  exception does not however invalidate any other reasons why the
+--  executable file might be covered by the GNU Public License.
+--
+--  This software was originally developed by the following company, and was
+--  released as open-source software as a service to the community:
+--
+--           FlightSafety International Simulation Systems Division
+--                    Broken Arrow, OK  USA  918-259-4000
+--
+-------------------------------------------------------------------------------
+
+with Ada.Strings.Maps;
+with Ada.Characters.Latin_1;
+
+-----------------------------------------------------------------------------
+--  This package implements a token recognizer for a token of any
+--  number of characters from a given set. The most useful use of this
+--  facility in a typical application is locating strings of
+--  "whitespace"
+-----------------------------------------------------------------------------
+package OpenToken.Recognizer.Single_Character_Set is
+
+   type Instance is new OpenToken.Recognizer.Instance with private;
+
+   --------------------------------------------------------------------------
+   --  This procedure will be called to create a Character_Set token.
+   --  Set should be given a string containing all the characters that
+   --  can be the single character token. The Set may be created using the
+   --  operations in Ada.Strings.Maps.
+   --
+   --------------------------------------------------------------------------
+   function Get (Set : in Ada.Strings.Maps.Character_Set) return Instance;
+
+private
+
+
+   type State_ID is (First_Char, Done);
+
+   type Instance is new OpenToken.Recognizer.Instance with record
+
+      --  The finite state machine state
+      State : State_ID := First_Char;
+
+      Set   : Ada.Strings.Maps.Character_Set;
+
+   end record;
+
+   overriding procedure Clear (The_Token : in out Instance);
+
+   overriding procedure Analyze
+     (The_Token : in out Instance;
+      Next_Char : in     Character;
+      Verdict   :    out Analysis_Verdict);
+
+end OpenToken.Recognizer.Single_Character_Set;
diff --git a/ada/printer.adb b/ada/printer.adb
new file mode 100644 (file)
index 0000000..7291e5c
--- /dev/null
@@ -0,0 +1,13 @@
+package body Printer is
+
+   function Pr_Str (M : Types.Mal_Type_Access) return String is
+      use Types;
+   begin
+     if M = null then
+        return "";
+     else
+        return To_String (M.all);
+     end if;
+   end Pr_Str;
+
+end Printer;
diff --git a/ada/printer.ads b/ada/printer.ads
new file mode 100644 (file)
index 0000000..0d2c78d
--- /dev/null
@@ -0,0 +1,7 @@
+with Types;
+
+package Printer is
+
+   function Pr_Str (M : Types.Mal_Type_Access) return String;
+
+end Printer;
diff --git a/ada/reader.adb b/ada/reader.adb
new file mode 100644 (file)
index 0000000..be40508
--- /dev/null
@@ -0,0 +1,205 @@
+with Ada.IO_Exceptions;
+with Ada.Characters.Latin_1;
+with Ada.Strings.Maps.Constants;
+with Ada.Strings.Unbounded;
+with Ada.Text_IO;
+with Opentoken.Recognizer.Character_Set;
+with Opentoken.Recognizer.Identifier;
+with Opentoken.Recognizer.Integer;
+with Opentoken.Recognizer.Keyword;
+with Opentoken.Recognizer.Line_Comment;
+with Opentoken.Recognizer.Separator;
+with Opentoken.Recognizer.Single_Character_Set;
+with Opentoken.Recognizer.String;
+with OpenToken.Text_Feeder.String;
+with Opentoken.Token.Enumerated.Analyzer;
+
+package body Reader is
+
+   type Lexemes is (Int, Sym,
+                    Nil, True_Tok, False_Tok, Exp_Tok,
+                    Str, Atom,
+                    Whitespace, Comment);
+
+   package Lisp_Tokens is new Opentoken.Token.Enumerated (Lexemes);
+   package Tokenizer is new Lisp_Tokens.Analyzer;
+
+   Exp_Recognizer   : constant Tokenizer.Recognizable_Token :=
+     Tokenizer.Get(Opentoken.Recognizer.Separator.Get ("**"));
+
+   Nil_Recognizer   : constant Tokenizer.Recognizable_Token :=
+     Tokenizer.Get(Opentoken.Recognizer.Keyword.Get ("nil"));
+
+   True_Recognizer : constant Tokenizer.Recognizable_Token :=
+     Tokenizer.Get(Opentoken.Recognizer.Keyword.Get ("true"));
+
+   False_Recognizer : constant Tokenizer.Recognizable_Token :=
+     Tokenizer.Get(Opentoken.Recognizer.Keyword.Get ("false"));
+
+   ID_Recognizer   : constant Tokenizer.Recognizable_Token :=
+     Tokenizer.Get(Opentoken.Recognizer.Identifier.Get);
+
+   Int_Recognizer  : constant Tokenizer.Recognizable_Token :=
+     Tokenizer.Get(Opentoken.Recognizer.Integer.Get);
+
+   String_Recognizer  : constant Tokenizer.Recognizable_Token :=
+     Tokenizer.Get(Opentoken.Recognizer.String.Get);
+
+   -- Atom definition
+   Start_Chars : Ada.Strings.Maps.Character_Set :=
+     Ada.Strings.Maps.Constants.Letter_Set;
+
+   Body_Chars : Ada.Strings.Maps.Character_Set :=
+     Ada.Strings.Maps."or"
+       (Ada.Strings.Maps.Constants.Alphanumeric_Set,
+        Ada.Strings.Maps.To_Set ('-'));
+
+   Atom_Recognizer  : constant Tokenizer.Recognizable_Token :=
+     Tokenizer.Get
+       (Opentoken.Recognizer.Identifier.Get (Start_Chars, Body_Chars));
+
+   Lisp_Syms : constant Ada.Strings.Maps.Character_Set :=
+     Ada.Strings.Maps.To_Set ("[]{}()'`~^@+-*/");
+
+   Sym_Recognizer : constant Tokenizer.Recognizable_Token :=
+     Tokenizer.Get (Opentoken.Recognizer.Single_Character_Set.Get (Lisp_Syms));
+
+   Lisp_Whitespace : constant Ada.Strings.Maps.Character_Set :=
+     Ada.Strings.Maps.To_Set (Ada.Characters.Latin_1.HT &
+                              Ada.Characters.Latin_1.Space &
+                              Ada.Characters.Latin_1.Comma);
+
+   Whitesp_Recognizer : constant Tokenizer.Recognizable_Token :=
+     Tokenizer.Get (Opentoken.Recognizer.Character_Set.Get (Lisp_Whitespace));
+
+   Comment_Recognizer  : constant Tokenizer.Recognizable_Token :=
+     Tokenizer.Get(Opentoken.Recognizer.Line_Comment.Get (";"));
+
+   Syntax : constant Tokenizer.Syntax :=
+     (Int           => Int_Recognizer,
+      Sym => Sym_Recognizer,
+      Nil           => Nil_Recognizer,
+      True_Tok      => True_Recognizer,
+      False_Tok     => False_Recognizer,
+      Exp_Tok       => Exp_Recognizer,
+      Str           => String_Recognizer,
+      Atom          => Atom_Recognizer,
+      Whitespace    => Whitesp_Recognizer,
+      Comment       => Comment_Recognizer  --,
+     );
+
+   Input_Feeder : aliased OpenToken.Text_Feeder.String.Instance;
+
+   Analyzer : Tokenizer.Instance :=
+     Tokenizer.Initialize (Syntax, Input_Feeder'access);
+
+
+   function Get_Token_String return String is
+   begin
+      return Tokenizer.Lexeme (Analyzer);
+   end Get_Token_String;
+
+
+   function Get_Token_Char return Character is
+      S : String := Tokenizer.Lexeme (Analyzer);
+   begin
+      return S(S'First);
+   end Get_Token_Char;
+
+
+   function Get_Token return Types.Mal_Type_Access is
+      Res : Types.Mal_Type_Access;
+   begin
+      Tokenizer.Find_Next (Analyzer);
+      case Tokenizer.ID (Analyzer) is
+         when Int =>
+            Res := new Types.Mal_Type'
+              (Sym_Type => Types.Int,
+               Int_Val => Integer'Value (Get_Token_String));
+         when Sym =>
+            Res := new Types.Mal_Type'
+              (Sym_Type => Types.Sym, Symbol => Get_Token_Char);
+         when Nil =>
+            Res := new Types.Mal_Type'
+              (Sym_Type => Types.Atom,
+               The_Atom => Ada.Strings.Unbounded.To_Unbounded_String
+                        (Get_Token_String));
+         when True_Tok =>
+            Res := new Types.Mal_Type'
+              (Sym_Type => Types.Atom,
+               The_Atom => Ada.Strings.Unbounded.To_Unbounded_String
+                        (Get_Token_String));
+         when False_Tok =>
+            Res := new Types.Mal_Type'
+              (Sym_Type => Types.Atom,
+               The_Atom => Ada.Strings.Unbounded.To_Unbounded_String
+                        (Get_Token_String));
+         when Exp_Tok =>
+            Res := new Types.Mal_Type'
+              (Sym_Type => Types.Atom,
+               The_Atom => Ada.Strings.Unbounded.To_Unbounded_String
+                        (Get_Token_String));
+         when Str =>
+            Res := new Types.Mal_Type'
+              (Sym_Type => Types.Str,
+               The_String => Ada.Strings.Unbounded.To_Unbounded_String
+                        (Get_Token_String));
+         when Atom =>
+            Res := new Types.Mal_Type'
+              (Sym_Type => Types.Atom,
+               The_Atom => Ada.Strings.Unbounded.To_Unbounded_String
+                        (Get_Token_String));
+         when Whitespace | Comment => null;
+      end case;
+      return Res;
+   end Get_Token;
+
+
+   -- Parsing
+   function Read_Form return Types.Mal_Type_Access;
+
+   function Read_List return Types.Mal_Type_Access is
+      use types;
+      List_MT, MTA : Types.Mal_Type_Access;
+   begin
+      List_MT := new Types.Mal_Type'
+                       (Sym_Type => Types.List, 
+                        The_List => Types.Lists.Empty_List);
+      loop
+         MTA := Read_Form;
+         exit when MTA = null or else
+                   MTA.all = (Sym_Type => Sym, Symbol => ')');
+         Types.Lists.Append (List_MT.The_List, MTA);
+      end loop;
+      return List_MT;
+   end Read_List;
+
+
+   function Read_Form return Types.Mal_Type_Access is
+      use Types;
+      MT : Types.Mal_Type_Access;
+   begin
+      MT := Get_Token;
+      if MT.all = (Sym_Type => Sym, Symbol => '(') then
+         return Read_List;
+      else
+         return MT;
+      end if;
+   end Read_Form;
+
+
+   function Read_Str (S : String) return Types.Mal_Type_Access is
+   begin
+      Analyzer.Reset;
+      Input_Feeder.Set (S);
+      return Read_Form;
+   exception
+      when OPENTOKEN.SYNTAX_ERROR =>
+         Ada.Text_IO.Put_Line
+           (Ada.Text_IO.Standard_Error,
+            "Lexical error at char " & Integer'Image (Analyzer.Line));
+         raise Ada.IO_Exceptions.End_Error;
+   end Read_Str;
+   
+
+end Reader;
diff --git a/ada/reader.ads b/ada/reader.ads
new file mode 100644 (file)
index 0000000..9255af1
--- /dev/null
@@ -0,0 +1,9 @@
+with Types;
+
+package Reader is
+
+   -- This is the Parser (returns an AST)
+   function Read_Str (S : String) return Types.Mal_Type_Access;
+   --function Read_Str return Types.Mal_Type_Access;
+   
+end Reader;
diff --git a/ada/step0_repl.gpr b/ada/step0_repl.gpr
new file mode 100644 (file)
index 0000000..0140abd
--- /dev/null
@@ -0,0 +1,7 @@
+project Step0_Repl is
+
+   for Object_Dir use "obj";
+   for Exec_Dir use ".";
+   for Main use ("step0_repl.adb");
+
+end Step0_Repl;
diff --git a/ada/step1_read_print.adb b/ada/step1_read_print.adb
new file mode 100644 (file)
index 0000000..a6972cd
--- /dev/null
@@ -0,0 +1,49 @@
+with Ada.Text_IO;
+with Ada.IO_Exceptions;
+with Printer;
+with Reader;
+with Types;
+
+procedure Step1_Read_Print is
+
+   function Read (Param : String) return Types.Mal_Type_Access is
+   --function Read return Types.Mal_Type_Access is
+   begin
+      return Reader.Read_Str (Param);
+      --return Reader.Read_Str;
+   end Read;
+
+   function Eval (Param : Types.Mal_Type_Access) return Types.Mal_Type_Access is
+   begin
+      return Param;
+   end Eval;
+
+   function Print (Param : Types.Mal_Type_Access) return String is
+   begin
+      return Printer.Pr_Str (Param);
+   end Print;
+
+   function Rep (Param : String) return String is
+   --function Rep return String is
+     AST : Types.Mal_Type_Access := Read (Param);
+     Eval_Str : Types.Mal_Type_Access := Eval (AST);
+     Print_Str : String := Print (Eval_Str);
+   begin
+     return Print_Str;
+   end Rep; 
+
+   S : String (1..1024);
+   Last : Natural;
+
+begin
+
+   loop
+      Ada.Text_IO.Put ("user> ");
+      Ada.Text_IO.Get_Line (S, Last);
+      Ada.Text_IO.Put_Line (Rep (S(1..Last)));
+   end loop;
+
+exception
+   when Ada.IO_Exceptions.End_Error => null;
+   -- i.e. exit without textual output
+end Step1_Read_Print;
diff --git a/ada/step1_read_print.gpr b/ada/step1_read_print.gpr
new file mode 100644 (file)
index 0000000..207154a
--- /dev/null
@@ -0,0 +1,9 @@
+with "opentoken";
+
+project Step1_Read_Print is
+
+   for Object_Dir use "obj";
+   for Exec_Dir use ".";
+   for Main use ("step1_read_print.adb");
+
+end Step1_Read_Print;
diff --git a/ada/types.adb b/ada/types.adb
new file mode 100644 (file)
index 0000000..97666b4
--- /dev/null
@@ -0,0 +1,58 @@
+with Ada.Characters.Latin_1;
+with Ada.Text_IO;
+
+package body Types is
+
+   package ACL renames Ada.Characters.Latin_1;
+
+   function To_String (T : Mal_Type) return String is
+      use Ada.Strings.Unbounded;
+   begin
+      case T.Sym_Type is
+         when Int =>
+            declare
+               Res : String := Integer'Image (T.Int_Val);
+            begin
+               if Res (1) = ' ' then
+                 return Res (2..Res'Last);
+               else
+                 return "int> " & Res;
+               end if;
+            end;
+         when List =>
+
+            declare
+               UBS : Unbounded_String := Null_Unbounded_String;
+               C : Lists.Cursor;
+               use type Lists.Cursor;
+               First_Pass : Boolean := True;
+            begin
+               if Lists.Is_Empty (T.The_List) then
+                  return "()";
+               end if;
+               C := Lists.First (T.The_List);
+               loop
+                  if First_Pass then
+                     First_Pass := False;
+                  else
+                     Append (UBS, " ");
+                  end if;
+                  UBStrings.Append (UBS, To_String (Lists.Element (C).all));
+               exit when C = Lists.Last (T.The_List);
+                  C := Lists.Next (C);
+               end loop;
+               return "(" & To_String (UBS) & ")";
+            end;
+         when Sym =>
+            return "" & T.Symbol;
+         when Str =>
+            -- The_String includes the quotation marks.
+            return To_String (T.The_String);
+         when Atom =>
+            return To_String (T.The_Atom);
+         when EOLine =>
+            return "";
+      end case;
+   end To_String;
+
+end Types;
diff --git a/ada/types.ads b/ada/types.ads
new file mode 100644 (file)
index 0000000..d36749a
--- /dev/null
@@ -0,0 +1,32 @@
+with Ada.Containers.Doubly_Linked_Lists;
+with Ada.Strings.Unbounded;
+
+package Types is
+
+   package UBStrings renames Ada.Strings.Unbounded;
+
+   type Mal_Type;
+
+   type Mal_Type_Access is access all Mal_Type;
+
+   package Lists is
+     new Ada.Containers.Doubly_Linked_Lists
+       (Element_Type => Mal_Type_Access,
+        "=" => "=");
+
+   type Sym_Types is (Int, List, Sym, Str, Atom, EOLine);
+
+   type Mal_Type (Sym_Type : Sym_Types) is record
+      case Sym_Type is
+         when Int => Int_Val : Integer;
+         when List => The_List : Lists.List;
+         when Sym => Symbol : Character;
+         when Str => The_String : Ada.Strings.Unbounded.Unbounded_String;
+         when Atom => The_Atom : Ada.Strings.Unbounded.Unbounded_String;
+         when EOLine => null;
+      end case;
+   end record;
+
+   function To_String (T : Mal_Type) return String;
+
+end Types;