浏览代码

improved interpreter shell with lax syntax

git-svn-id: https://svn.inf.ethz.ch/svn/lecturers/a2/trunk@6660 8c9fc860-2736-0410-a75d-ab315db34111
felixf 9 年之前
父节点
当前提交
9ecc7d4926
共有 5 个文件被更改,包括 370 次插入235 次删除
  1. 109 179
      source/FoxInterpreter.Mod
  2. 112 37
      source/FoxParser.Mod
  3. 13 7
      source/FoxScanner.Mod
  4. 129 8
      source/InterpreterShell.Mod
  5. 7 4
      source/WMInterpreterShell.Mod

+ 109 - 179
source/FoxInterpreter.Mod

@@ -1,7 +1,7 @@
 MODULE FoxInterpreter; (** AUTHOR ""; PURPOSE ""; *)
 
 IMPORT Scanner := FoxScanner, FoxParser, SyntaxTree := FoxSyntaxTree, Printout := FoxPrintout, Commands, Diagnostics, StringPool, InterpreterSymbols := FoxInterpreterSymbols, D:= Debugging,
-	Strings, Streams, Modules, PersistentObjects, Basic := FoxBasic, SYSTEM, Machine;
+	Strings, Streams, Modules, PersistentObjects, Basic := FoxBasic, SYSTEM, Machine, Global := FoxGlobal;
 
 CONST
 	EnableTrace = FALSE;
@@ -18,11 +18,16 @@ TYPE
 	Set*=InterpreterSymbols.SetValue;
 	Range*=InterpreterSymbols.RangeValue;
 	Char*=InterpreterSymbols.CharValue;
+	Any*=InterpreterSymbols.AnyValue;
 	MathArrayValue*= InterpreterSymbols.MathArrayValue;
 	
 	Scope*=InterpreterSymbols.Scope;
 	Container*= InterpreterSymbols.Container;
 	
+	Builtin*=OBJECT (InterpreterSymbols.Object)
+	VAR id: LONGINT;
+	END Builtin;
+	
 	Item*= RECORD
 		object*: InterpreterSymbols.Item;
 		in*: InterpreterSymbols.Item;
@@ -75,152 +80,6 @@ TYPE
 
 	END Parser;
 
-
-	Callstack = OBJECT
-	VAR 
-		data: ARRAY 1024 OF CHAR;
-		pos: LONGINT;
-		size: LONGINT;
-		H: HUGEINT; (* result in register *)
-		
-		retType: Modules.FieldEntry;
-		parameters: POINTER TO ARRAY OF Modules.FieldEntry;
-		pPos: LONGINT;
-		
-		PROCEDURE & Init;
-		BEGIN
-			pos := 1024; size := 0;
-		END Init;
-		
-		PROCEDURE Next(s: SIZE): ADDRESS;
-		BEGIN
-			DEC(pos, s); INC(size, s);
-			RETURN ADDRESSOF(data[pos]);
-		END Next;
-		
-		PROCEDURE PushH(h: HUGEINT);
-		VAR p: POINTER {UNSAFE} TO RECORD h: HUGEINT END;
-		BEGIN
-			p := Next(SIZEOF(HUGEINT));
-			p.h := h;
-		END PushH;
-
-		PROCEDURE PushL(i: LONGINT);
-		VAR p: POINTER {UNSAFE} TO RECORD i: LONGINT END;
-		BEGIN
-			p := Next(SIZEOF(LONGINT));
-			p.i := i;
-		END PushL;
-
-		PROCEDURE PushI(i: INTEGER);
-		BEGIN
-			PushL(i);
-		END PushI;		
-
-		PROCEDURE PushS(i: SHORTINT);
-		BEGIN
-			PushL(i);
-		END PushS;		
-		
-		PROCEDURE PushC(c: CHAR);
-		BEGIN
-			PushL(ORD(c));
-		END PushC;
-		
-		PROCEDURE PushR(r: REAL);
-		VAR p: POINTER {UNSAFE} TO RECORD r: REAL END;
-		BEGIN
-			p := Next(SIZEOF(REAL));
-			p.r := r;
-		END PushR;
-		
-		PROCEDURE PushX(x: LONGREAL);
-		VAR p: POINTER {UNSAFE} TO RECORD x: LONGREAL END;
-		BEGIN
-			p := Next(SIZEOF(LONGREAL));
-			p.x := x;
-		END PushX;
-		
-		PROCEDURE PushA(a: ADDRESS);
-		VAR p: POINTER {UNSAFE} TO RECORD a: ADDRESS END;
-		BEGIN
-			p := Next(SIZEOF(ADDRESS));
-			p.a := a;
-		END PushA;
-
-
-		PROCEDURE PushSz(s: SIZE);
-		VAR p: POINTER {UNSAFE} TO RECORD s: SIZE END;
-		BEGIN
-			p := Next(SIZEOF(SIZE));
-			p.s := s;
-		END PushSz;
-		
-		PROCEDURE Call(adr: ADDRESS);
-		VAR esp: ADDRESS; P: Procedure; h: HUGEINT
-		TYPE 
-			Procedure = PROCEDURE(): HUGEINT;
-		BEGIN
-			P := SYSTEM.VAL(Procedure, adr); 
-			esp := Machine.CurrentSP();
-			Machine.SetSP(esp-size);
-			SYSTEM.MOVE(ADDRESS OF data[pos], esp-size, size);
-			H := P();
-			Machine.SetSP(esp);
-		END Call;
-		
-		PROCEDURE ResH(): HUGEINT;
-		BEGIN
-			RETURN H;
-		END ResH;
-
-		PROCEDURE ResL(): LONGINT;
-		BEGIN
-			RETURN LONGINT(H);
-		END ResL;
-
-		PROCEDURE ResI(): INTEGER;
-		BEGIN
-			RETURN INTEGER(H);
-		END ResI;
-
-		PROCEDURE ResS(): SHORTINT;
-		BEGIN
-			RETURN SHORTINT(H);
-		END ResS;
-
-		PROCEDURE ResC(): CHAR;
-		BEGIN
-			RETURN CHR(H);
-		END ResC;
-
-		PROCEDURE ResSet(): SET;
-		BEGIN
-			RETURN SYSTEM.VAL(SET,H);
-		END ResSet;
-
-		PROCEDURE ResSz(): SIZE;
-		BEGIN
-			RETURN SYSTEM.VAL(SIZE, H);
-		END ResSz;
-
-		PROCEDURE ResA(): ADDRESS;
-		BEGIN
-			RETURN SYSTEM.VAL(ADDRESS, H)
-		END ResA;
-
-		PROCEDURE ResR(): REAL;
-		BEGIN
-			RETURN SYSTEM.VAL(REAL, ResL())
-		END ResR;
-
-		PROCEDURE ResX(): LONGREAL;
-		BEGIN
-			RETURN SYSTEM.VAL(LONGREAL, ResH())
-		END ResX;
-
-	END Callstack;
-
 	Interpreter* = OBJECT (SyntaxTree.Visitor)
 	VAR
 		value: BOOLEAN;
@@ -234,7 +93,6 @@ TYPE
 		error-: BOOLEAN;
 		diagnostics: Diagnostics.Diagnostics;
 		context-: Commands.Context;
-		callStack: Callstack;
 		
 		
 		PROCEDURE & Init*(scope: Scope; diagnostics: Diagnostics.Diagnostics; context: Commands.Context);
@@ -244,7 +102,6 @@ TYPE
 			error := FALSE;
 			SELF.diagnostics := diagnostics;
 			SELF.context := context;
-			NEW(callStack);
 		END Init;
 
 		PROCEDURE SetScope*(s: Scope);
@@ -556,16 +413,27 @@ TYPE
 
 		PROCEDURE VisitIdentifierDesignator*(x: SyntaxTree.IdentifierDesignator);
 		VAR moduleName: Modules.Name; msg: ARRAY 128 OF CHAR; res: LONGINT;
+			 builtin : Builtin; anyValue: Any;
 		BEGIN
 			ASSERT(x.left = NIL);
 			item.name := x.identifier;
 			(*
 			item.object := FindInScope(item.scope, item.name);
 			*)
-			item.object := scope.FindObject1(item.name, -1, item.in);
-			IF item.object = NIL THEN
-				StringPool.GetString(item.name, moduleName);
-				item.object :=InterpreterSymbols.GetModule(moduleName); 
+			IF item.name = Basic.MakeString("trace") THEN 
+				NEW(builtin); builtin.id :=  Global.systemTrace;
+				item.object := builtin;
+			ELSIF item.name = Basic.MakeString("context") THEN
+				NEW(anyValue, context);
+				item.object :=  anyValue;
+			ELSE
+				
+				item.object := scope.FindObject1(item.name, -1, item.in);
+				
+				IF item.object = NIL THEN
+					StringPool.GetString(item.name, moduleName);
+					item.object :=InterpreterSymbols.GetModule(moduleName); 
+				END;
 			END;
 		END VisitIdentifierDesignator;
 
@@ -596,27 +464,38 @@ TYPE
 		BEGIN
 			e := x.left;
 			Expression(e);
-			IF (item.object # NIL) & (item.object IS InterpreterSymbols.ProcedureResult) THEN
-				proc := item.object(InterpreterSymbols.ProcedureResult);
-				(* self pointer *) 
-				proc.Pars();
-				IF ~(proc.caller IS InterpreterSymbols.ModuleResult) THEN
-					adrValue := proc.caller.Evaluate();
-					ASSERT(adrValue.GetAddress(adr)); 
-					proc.PushAddress(adr);
-				END;
-				(* result pointer *) 
-				IF proc.ReturnsPointer() THEN
-					NEW(any,NIL);
-					proc.PushAddress(any.Address());
-				END; 
-				FOR i := 0 TO x.parameters.Length()-1 DO
-					e := x.parameters.GetExpression(i);
-					IF ~proc.Push(Designate(e)) THEN Error("wrong parameter"); RETURN END;
+			IF (item.object # NIL) THEN
+				IF (item.object IS InterpreterSymbols.ProcedureResult) THEN
+					proc := item.object(InterpreterSymbols.ProcedureResult);
+					(* self pointer *) 
+					proc.Pars();
+					IF ~(proc.caller IS InterpreterSymbols.ModuleResult) THEN
+						adrValue := proc.caller.Evaluate();
+						ASSERT(adrValue.GetAddress(adr)); 
+						proc.PushAddress(adr);
+					END;
+					(* result pointer *) 
+					IF proc.ReturnsPointer() THEN
+						NEW(any,NIL);
+						proc.PushAddress(any.Address());
+					END; 
+					FOR i := 0 TO x.parameters.Length()-1 DO
+						e := x.parameters.GetExpression(i);
+						IF ~proc.Push(Designate(e)) THEN Error("wrong parameter"); RETURN END;
+					END;
+					IF ~proc.Check() THEN Error("non-matching parameter number"); RETURN END; 
+					item.object := proc.Evaluate();
+					IF any # NIL THEN item.object := any END;
+				ELSIF (item.object IS Builtin) THEN
+					CASE item.object(Builtin).id OF
+					Global.systemTrace:
+						SystemTrace(x.parameters);
+					ELSE
+						Error("no builtin?")
+					END;
+				ELSE
+						Error("no procedure")
 				END;
-				IF ~proc.Check() THEN Error("non-matching parameter number"); RETURN END; 
-				item.object := proc.Evaluate();
-				IF any # NIL THEN item.object := any END;
 			ELSE
 				Error("no procedure")
 			END;
@@ -686,9 +565,59 @@ TYPE
 		PROCEDURE VisitProcedureCallDesignator*(x: SyntaxTree.ProcedureCallDesignator);
 		BEGIN HALT(100)
 		END VisitProcedureCallDesignator;
-
-		PROCEDURE VisitBuiltinCallDesignator*(x: SyntaxTree.BuiltinCallDesignator);
-		BEGIN HALT(100)
+		
+		PROCEDURE SystemTrace(x: SyntaxTree.ExpressionList);
+		VAR
+			printout: Printout.Printer;
+			value: Value;
+			expression: SyntaxTree.Expression;
+			i: LONGINT;
+			out: Streams.Writer;
+		BEGIN
+			out := context.out;
+			printout := Printout.NewPrinter(out,Printout.SourceCode,FALSE);
+			FOR i := 0 TO x.Length()-1 DO
+				expression := x.GetExpression(i);
+				IF ~(expression IS SyntaxTree.StringValue) THEN
+					printout.Expression(expression);
+					out.String("= ");
+				END;
+				value := Evaluate(expression);
+				IF value # NIL THEN
+					value.WriteValue(out);
+				ELSE
+					out.String("UNKNOWN")
+				END;
+				out.Ln;
+			END;
+			out.Update;
+		END SystemTrace;
+		
+		PROCEDURE VisitBuiltinCallDesignator(x: SyntaxTree.BuiltinCallDesignator);
+		VAR p,p0,p1,p2: SyntaxTree.Expression;
+			type,t0,t1,t2: SyntaxTree.Type;
+			len: LONGINT;
+			i: LONGINT; 
+			parameter: SyntaxTree.Parameter;
+			name: Basic.SectionName;
+			modifier: SyntaxTree.Modifier;
+			position: LONGINT;
+		BEGIN
+			position := x.position;
+			p0 := NIL; p1 := NIL; p2 := NIL; len := x.parameters.Length();
+			IF len > 0 THEN p0 := x.parameters.GetExpression(0); t0 := p0.type.resolved END;
+			IF len > 1 THEN p1 := x.parameters.GetExpression(1); t1 := p1.type.resolved END;
+			IF len > 2 THEN p2 := x.parameters.GetExpression(2); t2 := p2.type.resolved END;
+
+			CASE x.id OF
+			(* ----- NEW -----*)
+			Global.New:
+				Error("Not Yet Implemented");
+			|Global.systemTrace:
+				SystemTrace(x.parameters);
+			ELSE (* function not yet implemented *)
+				Error("Not Yet Implemented");
+			END;
 		END VisitBuiltinCallDesignator;
 
 		PROCEDURE VisitTypeGuardDesignator*(x: SyntaxTree.TypeGuardDesignator);
@@ -1008,7 +937,9 @@ TYPE
 		VAR value: Value;
 		BEGIN
 			IF GetValue(x.right, value) THEN
-				PutValue(x.left, value);
+				IF x.left # NIL THEN
+					PutValue(x.left, value);
+				END;
 			END;
 		END VisitAssignment;
 
@@ -1136,8 +1067,7 @@ TYPE
 			x.Accept(SELF);			
 		END Expression;
 		
-		
-		PROCEDURE Statement(x: SyntaxTree.Statement);
+		PROCEDURE Statement*(x: SyntaxTree.Statement);
 		BEGIN
 			item.object := NIL;
 			x.Accept(SELF);

+ 112 - 37
source/FoxParser.Mod

@@ -6,7 +6,6 @@ IMPORT Basic := FoxBasic, Scanner := FoxScanner, D := Debugging, SyntaxTree := F
 CONST
 	Trace = FALSE;	
 	CascadedWithSupport = TRUE;
-	Lax=FALSE;
 
 	(** the parser reflects the following EBNF:
 
@@ -175,8 +174,10 @@ TYPE
 		recentComment: SyntaxTree.Comment;
 		moduleScope: SyntaxTree.ModuleScope;
 		error-: BOOLEAN;
+		Lax-: BOOLEAN;
 
 		indent: LONGINT;   (* for debugging purposes only *)
+		hasSymbol: BOOLEAN;
 
 		PROCEDURE S( CONST s: ARRAY OF CHAR );   (* for debugging purposes only *)
 		VAR i: LONGINT;
@@ -192,6 +193,7 @@ TYPE
 			D.Ln;  D.Int( indent,1 );
 			FOR i := 1 TO indent DO D.Str( "  " );  END;
 			D.Str( "end : " );  D.Str( s );  D.Str( " at pos " );  D.Int( symbol.start,1 );
+			DEC(indent);
 		END E;
 
 		PROCEDURE EE( CONST s, t: ARRAY OF CHAR );   (* for debugging purposes only *)
@@ -200,6 +202,7 @@ TYPE
 			D.Ln;  D.Int( indent,1 );
 			FOR i := 1 TO indent DO D.Str( "  " );  END;
 			D.Str( "end : " );  D.Str( s );  D.Str( " (" );  D.Str( t );  D.Str( ") at pos " );
+			DEC(indent);
 		END EE;
 
 		(** constructor, init parser with scanner providing input and with diagnostics for error output *)
@@ -208,10 +211,19 @@ TYPE
 			SELF.scanner := scanner;
 			SELF.diagnostics := diagnostics;
 			error := ~scanner.GetNextSymbol(symbol);
+			hasSymbol := TRUE;
+			IF error THEN diagnostics.Error(scanner.source^, Diagnostics.Invalid, Diagnostics.Invalid, "no input stream") END;
 			recentCommentItem := NIL; recentComment := NIL;
 			(* debugging *)
 			indent := 0;
+			Lax := FALSE;
 		END Init;
+		
+		PROCEDURE SetLax*;
+		BEGIN
+			Lax := TRUE;
+		END SetLax;
+		
 
 		(** output error message and / or given code *)
 		PROCEDURE Error(position: LONGINT; code: LONGINT; CONST message: ARRAY OF CHAR);
@@ -226,10 +238,10 @@ TYPE
 
 		(** helper procedures interfacing to the scanner **)
 
-		PROCEDURE SkipComments();
+		PROCEDURE SkipComments(b: BOOLEAN);
 		VAR comment: SyntaxTree.Comment;
 		BEGIN
-			WHILE ~error & (symbol.token = Scanner.Comment) DO
+			WHILE ~error & (b & (TokenB()= Scanner.Comment) OR ~b & (Token() = Scanner.Comment)) DO
 				comment := SyntaxTree.NewComment(symbol.start, currentScope, symbol.string^,symbol.stringLength);
 				IF moduleScope # NIL THEN
 					moduleScope.AddComment(comment);
@@ -265,7 +277,8 @@ TYPE
 						END;
 					END;
 				END;
-				error := ~scanner.GetNextSymbol(symbol);
+				NextSymbol;
+				(*error := ~scanner.GetNextSymbol(symbol);*)
 			END;
 		END SkipComments;
 
@@ -273,16 +286,51 @@ TYPE
 		PROCEDURE NextSymbol*;
 		VAR comment: SyntaxTree.Comment;
 		BEGIN
-			error := ~scanner.GetNextSymbol(symbol) OR error;
-			SkipComments();
+			(*
+				error := ~scanner.GetNextSymbol(symbol) OR error;
+				hasSymbol := TRUE;
+				SkipComments();
+			*)
+			hasSymbol := FALSE;
 		END NextSymbol;
 
+		PROCEDURE Token*(): LONGINT;
+		BEGIN
+			IF ~hasSymbol OR (symbol.token = Scanner.Escape) THEN
+				error := ~scanner.GetNextSymbol(symbol) OR error;
+				IF symbol.token = Scanner.Escape THEN 
+					error := ~scanner.GetNextSymbol(symbol) OR error;
+				END;
+				hasSymbol := TRUE;
+				SkipComments(FALSE);
+			END;
+			RETURN symbol.token;
+		END Token;
+
+		(* stop on escape token *)
+		PROCEDURE TokenB*(): LONGINT;
+		BEGIN
+			IF ~hasSymbol THEN
+				error := ~scanner.GetNextSymbol(symbol) OR error;
+				hasSymbol := TRUE;
+				SkipComments(TRUE);
+			END;
+			RETURN symbol.token;
+		END TokenB;
+
+		(** Check if current symbol equals sym. If yes then return true, return false otherwise *)
+		PROCEDURE PeekB*(token: Scanner.Token): BOOLEAN;
+		VAR comment: SyntaxTree.Comment;
+		BEGIN
+			RETURN TokenB() = token
+		END PeekB;
+
 		(** Check if current symbol equals sym. If yes then return true, return false otherwise *)
 		PROCEDURE Peek*(token: Scanner.Token): BOOLEAN;
 		VAR comment: SyntaxTree.Comment;
 		BEGIN
-			SkipComments();
-			RETURN symbol.token = token
+			SkipComments(FALSE);
+			RETURN Token() = token
 		END Peek;
 
 		(** Check if the current symbol equals sym.If yes then read next symbol, report error otherwise. returns success value  *)
@@ -358,7 +406,7 @@ TYPE
 		BEGIN
 			IF name = SyntaxTree.invalidIdentifier THEN (* nothing to be expected *)
 				RETURN TRUE
-			ELSIF (symbol.token # Scanner.Identifier) OR (symbol.identifier # name) THEN
+			ELSIF (Token() # Scanner.Identifier) OR (symbol.identifier # name) THEN
 				Basic.GetString(name,string);
 				Error( symbol.start, Scanner.Identifier, string );
 				RETURN FALSE
@@ -392,6 +440,17 @@ TYPE
 			END
 		END Optional;
 
+		PROCEDURE OptionalB*( token: Scanner.Token ): BOOLEAN;
+		BEGIN
+			(* do not use for Identifier, String or Number, if the result is needed ! *)
+			IF PeekB(token) THEN
+				NextSymbol;
+				RETURN TRUE
+			ELSE
+				RETURN FALSE
+			END
+		END OptionalB;
+		
 		(* ignore one ore more symbols of type token *)
 		PROCEDURE Ignore(token: Scanner.Token);
 		BEGIN WHILE Optional(token) DO END;
@@ -540,7 +599,7 @@ TYPE
 				expression := SyntaxTree.NewRangeExpression(position, first, last, step)
 			ELSE
 				expression := SimpleExpression();
-				IF Optional(Scanner.Upto) THEN
+				IF OptionalB(Scanner.Upto) THEN
 					(* is range expression *)
 					first := expression;
 
@@ -580,7 +639,7 @@ TYPE
 				designator := SyntaxTree.NewSelfDesignator(position);
 			ELSIF Optional(Scanner.Result) THEN
 				designator := SyntaxTree.NewResultDesignator(position);
-			ELSIF (symbol.token = Scanner.Address) OR (symbol.token = Scanner.Size) OR (symbol.token = Scanner.Alias) THEN
+			ELSIF (Token() = Scanner.Address) OR (Token()=Scanner.Size) OR (Token() = Scanner.Alias) THEN
 				identifier := symbol.identifier;
 				designator := SyntaxTree.NewIdentifierDesignator(position,identifier);
 				NextSymbol;
@@ -591,14 +650,15 @@ TYPE
 
 			LOOP
 				position := symbol.start;
-				IF Optional( Scanner.LeftParenthesis ) THEN
+				IF OptionalB( Scanner.LeftParenthesis ) THEN
 					expressionList := SyntaxTree.NewExpressionList();
 					IF ~Optional( Scanner.RightParenthesis ) THEN
 						ExpressionList( expressionList );
 						Check( Scanner.RightParenthesis )
 					END;
 					designator := SyntaxTree.NewParameterDesignator( position,designator,expressionList);
-				ELSIF Optional( Scanner.Period ) THEN
+				ELSIF OptionalB( Scanner.Period ) THEN
+					IF ~Optional(Scanner.Identifier) THEN (* make sure symbol is read *) END;
 					CASE symbol.identifierString[0] OF
 						"a".."z", "A" .. "Z":
 					(*IF Peek(Scanner.Size) (* special rule: support for SYSTEM.SIZE *) THEN*)
@@ -607,20 +667,22 @@ TYPE
 						identifier := Identifier(position);
 					END;
 					designator := SyntaxTree.NewSelectorDesignator(position,designator,identifier);
-				ELSIF Optional( Scanner.LeftBracket ) THEN
+				ELSIF OptionalB( Scanner.LeftBracket ) THEN
 					expressionList := SyntaxTree.NewExpressionList();
 					IndexList( expressionList );
 					Check( Scanner.RightBracket );
 					designator:= SyntaxTree.NewBracketDesignator( position,designator,expressionList );
-				ELSIF Optional( Scanner.Arrow ) THEN
+				ELSIF OptionalB( Scanner.Arrow ) THEN
 					designator:= SyntaxTree.NewArrowDesignator( position,designator );
 				ELSE EXIT
 				END;
 			END;
 
-			IF Optional(Scanner.LeftBrace) THEN
+			IF OptionalB(Scanner.LeftBrace) THEN
 				designator.SetModifiers(Flags());
 			END;
+			
+			(*IF OptionalB(Scanner.Escape) THEN END; (* skip breaking signal *)*)
 
 			IF Trace THEN E( "Designator" ) END;
 			RETURN designator
@@ -671,7 +733,7 @@ TYPE
 		BEGIN
 			IF Trace THEN S( "Factor" ) END;
 			position := symbol.start;
-			CASE symbol.token OF
+			CASE Token() OF
 			| Scanner.Number:
 					IF (symbol.numberType = Scanner.Integer) THEN
 						factor := SyntaxTree.NewIntegerValue( position, symbol.integer);
@@ -694,8 +756,8 @@ TYPE
 					factor := SyntaxTree.NewStringValue( position, symbol.string );
 					factor.End( symbol.end );
 					NextSymbol;
-					WHILE (symbol.token = Scanner.String) OR (symbol.token = Scanner.Character) DO
-						IF symbol.token = Scanner.Character THEN
+					WHILE (Token() = Scanner.String) OR (Token() = Scanner.Character) DO
+						IF Token() = Scanner.Character THEN
 							factor(SyntaxTree.StringValue).AppendChar(symbol.character);
 						ELSE
 							factor(SyntaxTree.StringValue).Append(symbol.string);
@@ -733,7 +795,7 @@ TYPE
 					factor := SyntaxTree.NewUnaryExpression( position, factor, Scanner.Not );
 					factor.End( symbol.end );
 			| Scanner.Address, Scanner.Size, Scanner.Alias:
-					operator := symbol.token;
+					operator := Token();
 					factor := Designator();
 					IF Optional(Scanner.Of) THEN
 						factor := Designator();
@@ -752,7 +814,7 @@ TYPE
 				NextSymbol;  factor := SyntaxTree.invalidExpression;
 			END;
 			(* suffix *)
-			IF Optional(Scanner.Transpose) THEN
+			IF OptionalB(Scanner.Transpose) THEN
 				IF (factor IS SyntaxTree.UnaryExpression) & (factor(SyntaxTree.UnaryExpression).operator = Scanner.Transpose) THEN
 					(* transpose operator has higher precedence than not, reevaluate expression: *)
 					factor := factor(SyntaxTree.UnaryExpression).left;
@@ -775,8 +837,8 @@ TYPE
 			IF Trace THEN S( "Term" ) END;
 			position := symbol.start;
 			term := Factor();
-			WHILE (symbol.token >= Scanner.Times) & (symbol.token <= Scanner.And)  DO
-				operator := symbol.token;
+			WHILE (TokenB() >= Scanner.Times) & (TokenB() <= Scanner.And)  DO
+				operator := Token();
 				NextSymbol;
 				factor := Factor();
 				term := SyntaxTree.NewBinaryExpression( position, term, factor, operator );
@@ -795,14 +857,14 @@ TYPE
 			IF Trace THEN S( "SimpleExpression" ) END;
 			position := symbol.start;
 			IF Peek(Scanner.Plus) OR Peek(Scanner.Minus) THEN (* sign should be part of the factor *)
-				operator := symbol.token;
+				operator := Token();
 				NextSymbol;
 				term := Term();
 				expression := SyntaxTree.NewUnaryExpression( position, term, operator );
 			ELSE expression := Term();
 			END;
-			WHILE (symbol.token >= Scanner.Or) & (symbol.token <= Scanner.Minus) DO
-				operator := symbol.token;
+			WHILE (TokenB() >= Scanner.Or) & (TokenB() <= Scanner.Minus) DO
+				operator := Token();
 				NextSymbol;
 				term := Term();
 				expression := SyntaxTree.NewBinaryExpression( position, expression, term, operator );
@@ -824,12 +886,13 @@ TYPE
 			IF Trace THEN S( "Expression" ) END;
 			position := symbol.start;
 			expression := RangeExpression();
-			IF (symbol.token >= Scanner.Equal) & (symbol.token <= Scanner.Is) THEN
-				operator := symbol.token;
+			IF (TokenB() >= Scanner.Equal) & (TokenB() <= Scanner.Is) THEN
+				operator := Token();
 				NextSymbol;
 				rightExpression := RangeExpression();
 				expression := SyntaxTree.NewBinaryExpression(position, expression, rightExpression, operator );
 			END;
+			(*IF OptionalB(Scanner.Escape) THEN END; (* skip breaking escape *)*)
 			IF Trace THEN E( "Expression" ) END;
 			RETURN expression
 		END Expression;
@@ -890,16 +953,16 @@ TYPE
 			commToken: Scanner.Token;
 		BEGIN
 			IF Trace THEN S( "Statement" ) END;
-			CASE symbol.token OF
+			CASE Token() OF
 			| Scanner.Identifier, Scanner.Self, Scanner.Result:
 					designator := Designator();
 					position := symbol.start;
-					IF Optional( Scanner.Becomes ) THEN
+					IF OptionalB( Scanner.Becomes ) THEN
 						expression := Expression();
 						statement := SyntaxTree.NewAssignment( position, designator, expression,outer );
 						CommentStatement(statement);
-					ELSIF Peek(Scanner.ExclamationMark) OR Peek(Scanner.Questionmark) OR Peek(Scanner.LessLess) OR Peek(Scanner.GreaterGreater) THEN
-						commToken := symbol.token; 
+					ELSIF PeekB(Scanner.ExclamationMark) OR PeekB(Scanner.Questionmark) OR PeekB(Scanner.LessLess) OR PeekB(Scanner.GreaterGreater) THEN
+						commToken := Token(); 
 						NextSymbol;
 						expression := Expression();
 						statement := SyntaxTree.NewCommunicationStatement(position, commToken, designator, expression, outer);
@@ -910,6 +973,7 @@ TYPE
 						CommentStatement(statement);
 					END;
 					statements.AddStatement( statement );
+					(*IF OptionalB(Scanner.Escape) THEN END;*)
 					result := TRUE
 			| Scanner.If:
 					NextSymbol;
@@ -1051,7 +1115,7 @@ TYPE
 					NextSymbol;
 					returnStatement := SyntaxTree.NewReturnStatement( symbol.start, outer);
 					CommentStatement(returnStatement);
-					IF (symbol.token >= Scanner.Plus) & (symbol.token <= Scanner.Identifier) THEN
+					IF (Token() >= Scanner.Plus) & (Token() <= Scanner.Identifier) THEN
 						expression := Expression();
 						returnStatement.SetReturnValue( expression );
 					END;
@@ -1082,7 +1146,18 @@ TYPE
 			| Scanner.Finally: result := FALSE  (* end block by finally statement *)
 			| Scanner.Semicolon: result := FALSE (* allow the empty statement *)
 			(* builtin pseudo procedures are resolved by checker *)
-			ELSE (* Error( symbol.start, Scanner.Semicolon, "" ); *) result := FALSE;
+			ELSE 
+				result := FALSE;
+				(*
+				IF Lax THEN
+					expression := Expression();
+					statement := SyntaxTree.NewAssignment( position, NIL, expression,outer );
+					statements.AddStatement(statement);
+					result := ~error;
+				ELSE
+					result := FALSE;
+				END;
+				*)
 			END;
 			IF Trace THEN E( "Statement" ) END;
 			RETURN result
@@ -1526,7 +1601,7 @@ TYPE
 			ELSIF Optional( Scanner.Port) THEN type := PortType( position, parentScope)
 			ELSIF Optional( Scanner.Procedure ) THEN type := ProcedureType( position,parentScope);
 			ELSIF Optional( Scanner.Enum ) THEN type := EnumerationType( position,parentScope);
-			ELSIF (symbol.token = Scanner.Address) OR (symbol.token = Scanner.Size) THEN
+			ELSIF (Token() = Scanner.Address) OR (Token() = Scanner.Size) THEN
 				qualifiedIdentifier := SyntaxTree.NewQualifiedIdentifier(position,SyntaxTree.invalidIdentifier, symbol.identifier);
 				type := SyntaxTree.NewQualifiedType( qualifiedIdentifier.position, parentScope, qualifiedIdentifier );
 				NextSymbol;
@@ -1596,7 +1671,7 @@ TYPE
 				kind := SyntaxTree.VarParameter
 			ELSIF Optional( Scanner.Const ) THEN (* const parameter *)
 				kind := SyntaxTree.ConstParameter
-			ELSIF symbol.token # Scanner.Identifier THEN
+			ELSIF Token() # Scanner.Identifier THEN
 				Error(symbol.start,Scanner.Identifier,"");
 				RETURN
 			ELSE kind := SyntaxTree.ValueParameter
@@ -2105,7 +2180,7 @@ TYPE
 				END;
 				Check(Scanner.End);
 				IF ExpectThisIdentifier( moduleName ) THEN
-					IF symbol.token # Scanner.Period THEN
+					IF Token() # Scanner.Period THEN
 						Error(  symbol.start, Scanner.Period, "" )
 					ELSIF ~error & ~scanner.error THEN (* read ahead to read comments and to check for next module *)
 						scanner.ResetCase;

+ 13 - 7
source/FoxScanner.Mod

@@ -16,8 +16,8 @@ CONST
 	MaxLongrealExponent* = 308;   (* maximal longreal exponent *)
 
 	(* scanner constants *)
-	EOT* = 0X; LF* = 0AX; CR* = 0DX; TAB* = 09X;
-
+	EOT* = 0X; LF* = 0AX; CR* = 0DX; TAB* = 09X; ESC* = 1BX;
+ 
 TYPE
 	StringType* = Strings.String;
 	IdentifierType *= StringPool.Index;
@@ -59,7 +59,7 @@ CONST
 		Ln PC PCOffset
 		(* number types *)
 		Shortint Integer Longint Hugeint Real Longreal
-		Comment EndOfText
+		Comment EndOfText Escape
 		~
 	*)
 	None*= 0; 
@@ -98,7 +98,7 @@ CONST
 	Ln*= 105; PC*= 106; PCOffset*= 107; 
 	(* number types *)
 	Shortint*= 108; Integer*= 109; Longint*= 110; Hugeint*= 111; Real*= 112; Longreal*= 113; 
-	Comment*= 114; EndOfText*= 115; 
+	Comment*= 114; EndOfText*= 115; Escape *= 116;
 
 	SingleQuote = 27X;  DoubleQuote* = 22X;
 	Ellipsis = 7FX;   (* used in Scanner.GetNumber to return with ".." when reading an interval like 3..5 *)
@@ -323,6 +323,11 @@ TYPE
 		BEGIN
 			firstIdentifier := TRUE; case := Unknown;
 		END ResetCase;
+		
+		PROCEDURE SetCase*(c: LONGINT);
+		BEGIN
+			case := c;
+		END SetCase;		
 
 		(** report an error occured during scanning **)
 		PROCEDURE ErrorS(CONST msg: ARRAY OF CHAR);
@@ -831,7 +836,7 @@ TYPE
 
 		PROCEDURE SkipBlanks;
 		BEGIN
-			WHILE ch <= " " DO  (*ignore control characters*)
+			WHILE (ch <= " ") & (ch # ESC)  DO  (*ignore control characters*)
 				IF ch = EOT THEN
 					IF Trace THEN D.String("EOT"); D.Ln; END;
 					RETURN
@@ -849,6 +854,7 @@ TYPE
 			stringMaker.Clear;
 			CASE ch OF  (* ch > " " *)
 			EOT: s := EndOfText
+			|ESC: s := Escape;; GetNextCharacter
 			| DoubleQuote:
 					s := String; GetString(symbol,TRUE, TRUE, FALSE);
 			| SingleQuote:
@@ -939,7 +945,7 @@ TYPE
 						IF  (token >= 0) THEN s := token END;
 						IF (s = Module) OR (s=CellNet) THEN case := Lowercase END;
 					END;
-					IF firstIdentifier & (s # Module) & (s # CellNet) THEN case := Uppercase; s := Identifier END;
+					IF firstIdentifier & (s # Module) & (s # CellNet) & (case = Unknown) THEN case := Uppercase; s := Identifier END;
 			ELSE s := Identifier;  GetIdentifier( symbol );
 			END;
 			firstIdentifier := FALSE;
@@ -1108,7 +1114,7 @@ TYPE
 
 			PROCEDURE SkipBlanks;
 			BEGIN
-				WHILE (ch <= ' ') & (ch # CR) & (ch # LF) & (ch # EOT) DO  (* ignore control characters except line feeds *)
+				WHILE (ch <= ' ') & (ch # CR) & (ch # LF) & (ch # EOT)  DO  (* ignore control characters except line feeds *)
 					GetNextCharacter
 				END;
 			END SkipBlanks;

+ 129 - 8
source/InterpreterShell.Mod

@@ -256,7 +256,6 @@ TYPE
 
 		BEGIN
 			command := ""; currentIndex := -1;
-
 			LOOP
 				ch := context.in.Get();
 				IF IsAsciiCharacter(ch) THEN
@@ -282,6 +281,7 @@ TYPE
 							IF context.in.Peek() = EscapeChar2 THEN ch := context.in.Get(); HandleEscapeSequence;
 							ELSIF context.in.Peek() = 0DX THEN (* command *)
 								ch := context.in.Get();
+								INC(currentIndex); command[currentIndex] := ch;
 								EXIT;
 							ELSIF context.in.Peek () = Escape THEN
 								command[currentIndex+1] := 0X;
@@ -629,18 +629,127 @@ TYPE
 		END Execute;
 		*)
 
+		TYPE 
+		
+	StringType = POINTER TO ARRAY OF CHAR;
+	Reader* = OBJECT (Streams.Reader)
+	VAR length : LONGINT;
+			data : StringType;
+			rofs: LONGINT;
+
+		PROCEDURE &Init*(initialSize : LONGINT);
+		BEGIN
+			IF initialSize < 256 THEN initialSize := 256 END;
+			NEW(data, initialSize); length := 0; rofs := 0;
+			InitReader( Receive, initialSize )
+		END Init;
+
+		PROCEDURE Add*(CONST buf: ARRAY OF CHAR; ofs, len: LONGINT; propagate: BOOLEAN; VAR res: LONGINT);
+		VAR i,pos : LONGINT; n: StringType;
+		BEGIN{EXCLUSIVE}
+			IF length + len + 1 >= LEN(data) THEN
+				NEW(n, LEN(data) + len + 1); FOR i := 0 TO length - 1 DO n[i] := data[i] END;
+				data := n
+			END;
+			pos := (rofs + length) MOD LEN(data);
+			WHILE (len > 0) & (buf[ofs] # 0X) DO
+				data[pos] := buf[ofs];
+				pos := (pos+1) MOD LEN(data);
+				INC(ofs); INC(length); DEC(len)
+			END;
+		END Add;
+
+		PROCEDURE Receive( VAR buf: ARRAY OF CHAR;  ofs, size, min: LONGINT;  VAR len, res: LONGINT );
+		VAR o,pos: LONGINT;
+		BEGIN{EXCLUSIVE}
+			AWAIT(length >= min);
+			pos := rofs;
+			len := 0;
+			WHILE (length > 0)  & (size >0) DO
+				buf[ofs] := data[pos];
+				pos := (pos + 1) MOD LEN(data);
+				INC(ofs); DEC(length); INC(len); DEC(size);
+			END;
+			rofs := pos;
+			IF ofs < size THEN 
+				buf[ofs] := 0X; (* safety / trace *)
+			END;
+		END Receive;
+
+	END Reader;
+		
 		PROCEDURE Run;
 		VAR cmdList: Command; wait, exit: BOOLEAN; i : LONGINT; interpreter: Interpreter.Interpreter; s: Scanner.StringMaker; w: Streams.Writer; r: Streams.Reader;
-			scanner: Scanner.Scanner; parser: Interpreter.Parser; diagnostics: Diagnostics.StreamDiagnostics; seq: SyntaxTree.StatementSequence;
+			scanner: Scanner.Scanner; parser: Interpreter.Parser; 
+			
+			diagnostics: Diagnostics.StreamDiagnostics; seq: SyntaxTree.StatementSequence;
 			str: Scanner.StringType; len: LONGINT; container: Interpreter.Container; scope: Interpreter.Scope; e: SyntaxTree.Expression; value: Interpreter.Value;
+			reader: Reader; 
+			
+			runner: OBJECT
+			VAR 
+			r: Streams.Reader;
+			scanner: Scanner.Scanner; parser: Interpreter.Parser;
+			stm: SyntaxTree.Statement;
+			diagnostics: Diagnostics.Diagnostics;
+			seq: SyntaxTree.StatementSequence;
+			interpreter: Interpreter.Interpreter;
+			container: Interpreter.Container; scope: Interpreter.Scope; 
+			context: Commands.Context;
+
+				PROCEDURE &Init(r: Streams.Reader; diag: Diagnostics.Diagnostics; ctxt: Commands.Context);
+				BEGIN
+					 SELF.r := r; diagnostics := diag; SELF.r := r;
+					 context := ctxt;
+				END Init;
+				
+			BEGIN{ACTIVE}
+				ASSERT(diagnostics # NIL);
+				NEW(scanner,"", r, 0, diagnostics);
+				scanner.SetCase(Scanner.Lowercase);
+				NEW(parser, scanner, diagnostics); (* silent *) 
+				parser.SetLax;
+				
+				NEW(container);
+				NEW(scope, Interpreter.global, container);
+				NEW(interpreter, scope, diagnostics, context);
+				LOOP
+				(*diagnostics.Information("interpreter",Diagnostics.Invalid,Diagnostics.Invalid,"start statement");*)
+				seq := SyntaxTree.NewStatementSequence();
+				IF parser.Statement(seq, NIL) THEN
+					(*Printout.Info("executing ", seq);*)
+					interpreter.StatementSequence(seq);
+					context.out.Update;
+					WHILE parser.Optional(Scanner.Escape) OR parser.Optional(Scanner.Semicolon) DO 
+						(*TRACE(parser.Token());*)
+					END;
+					IF interpreter.error THEN interpreter.Reset END;
+				ELSE
+					diagnostics.Error("",Diagnostics.Invalid, Diagnostics.Invalid, "no statement"); 
+					IF ~parser.error THEN
+						parser.NextSymbol;
+					END;
+					(*NEW(scanner, "",r, 0, diagnostics);
+					NEW(parser, scanner, diagnostics); (* silent *)*)
+				END;
+				
+				END;
+			END; 
 		BEGIN
 			NEW(s,0);
 			w := s.GetWriter();
 			NEW(diagnostics, context.out);
 			exit := FALSE;
-			NEW(container);
+			(*NEW(container);
 			NEW(scope, Interpreter.global, container);
 			NEW(interpreter, scope, diagnostics, context);
+			*)
+			NEW(reader, 1024);
+			(*NEW(w, reader.Add,1024);*)
+			NEW(runner, reader, diagnostics, context);
+			
+			
+			(*seq := parser.StatementSequence(NIL);*)
 			WHILE ~close & ~exit & (context.in.res = Streams.Ok) DO
 				IF (prompt # "") THEN
 					context.out.Ln;
@@ -651,12 +760,21 @@ TYPE
 					context.out.Update
 				END;
 				s.Clear;
-				ReadCommand(w);w.Update;
+				ReadCommand(w);w.Char(Escape);w.Ln; w.Update;(*
 				context.out.Ln; context.out.String("------------");
 				context.out.Ln; context.out.Update;
+				*)
 				str := s.GetString(len);
+				reader.Add(str^,0,len,TRUE,res);
+				
+				
+				
+				
+				(*
 				NEW(scanner, "", s.GetReader(), 0, diagnostics);
 				NEW(parser, scanner, NIL); (* silent *)
+				*)
+				(*
 				e := parser.Expression();
 				interpreter.Reset;
 				IF ~parser.error & parser.Optional(Scanner.EndOfText) THEN
@@ -667,6 +785,8 @@ TYPE
 					str := s.GetString(len);
 					NEW(scanner, "", s.GetReader(), 0, diagnostics);
 					NEW(parser, scanner, diagnostics);
+					*)
+					(*
 					seq := parser.StatementSequence(NIL);
 					IF parser.Mandatory(Scanner.EndOfText) THEN
 						interpreter.StatementSequence(seq);
@@ -674,7 +794,8 @@ TYPE
 							context.out.String("[ok]");
 						END;
 					END;
-				END;
+					*)
+				(*END;*)
 			END;
 			context.out.Update; context.error.Update
 		END Run;
@@ -724,7 +845,7 @@ TYPE
 
 	BEGIN {ACTIVE, SAFE}
 		context.out.String(Version); context.out.Ln;
-		context.out.String("Evaluate statement sequence with SHIFT-ENTER"); context.out.Ln;
+		context.out.String("Enter statement sequence in lower case with lax syntax"); context.out.Ln;
 		context.out.Update;
 		Run;
 		IF (upcall # NIL) THEN upcall(ExitShell); END;
@@ -733,6 +854,6 @@ TYPE
 
 END InterpreterShell.
 
-SystemTools.Free Shell ~
+SystemTools.Free WMInterpreterShell InterpreterShell FoxInterpreter~
 
-WMShell.Open ~
+WMInterpreterShell.Open ~

+ 7 - 4
source/WMInterpreterShell.Mod

@@ -26,7 +26,7 @@ CONST
 
 	ReceiveBufferSize = 256;
 
-	Prompt = ">";
+	Prompt = "";
 
 	Backspace = 08X;
 	ESC = 1BX;
@@ -109,7 +109,7 @@ TYPE
 					editor.editor.tv.End(flags * Inputs.Ctrl # {}, flags * Inputs.Shift # {})
 				ELSIF (keySym = Inputs.KsBackSpace) & (flags * Inputs.Ctrl # {}) THEN  (*Ctrl Backspace *)
 					Clear;
-				ELSIF (keySym = Inputs.KsReturn) & (flags*Inputs.Shift # {}) THEN (* SHIFT ENTER *)
+				ELSIF (keySym = Inputs.KsReturn) & (flags*Inputs.Shift = {}) THEN (* ENTER *)
 					text.AcquireRead;
 					len := text.GetLength()-begPos;
 					
@@ -123,15 +123,18 @@ TYPE
 							r.ReadCh(u);
 							IF (u >= 32) & (u <= 126) THEN (* take only characters *)
 								buf[n] := CHR(u); INC(n);
-							END; buf[n] := 0X;
+							END; 
+							buf[n] := 0X;
 						END;
 					END;
 					text.ReleaseRead;
 					
 					IF len > 0 THEN
 						out.String(buf^);
-						out.Char(ESC); out.Char(0DX); out.Update;
+						out.Char(ESC);  out.Char(0DX); out.Update;
+						begPos := begPos + len;						
 					END;
+					editor.editor.KeyPressed(ucs,flags,keySym,handled);
 
 				ELSIF ((keySym = Inputs.KsLeft) OR (keySym = Inputs.KsUp) OR (keySym = Inputs.KsDown)) & (editor.editor.tv.cursor.GetPosition() = begPos) THEN