瀏覽代碼

SELF and SUPER are keywords for Eberon

Vladislav Folts 11 年之前
父節點
當前提交
234ae17d07
共有 12 個文件被更改,包括 161 次插入48 次删除
  1. 1 1
      build.py
  2. 11 12
      src/eberon/eberon_grammar.js
  3. 18 11
      src/grammar.js
  4. 4 5
      src/js/Lexer.js
  5. 1 2
      src/ob/Lexer.ob
  6. 88 5
      src/ob/Types.ob
  7. 9 8
      src/oberon/oberon_grammar.js
  8. 14 0
      test/1.py
  9. 2 0
      test/make_snapshot.cmd
  10. 1 1
      test/test_compile.cmd
  11. 1 1
      test/test_unit.js
  12. 11 2
      test/test_unit_eberon.js

+ 1 - 1
build.py

@@ -76,7 +76,7 @@ def build(out, use_git):
 
 
     link(['oc.js', 'oberon/oberon_grammar.js', 'eberon/eberon_grammar.js'],
     link(['oc.js', 'oberon/oberon_grammar.js', 'eberon/eberon_grammar.js'],
          os.path.join(out, 'oc.js'),
          os.path.join(out, 'oc.js'),
-         ['src', 'src/oberon.js'],
+         ['src', 'src/js'],
          version)
          version)
     copy('browser/oberonjs.html', out)
     copy('browser/oberonjs.html', out)
     for d in ['codemirror', 'jslibs']:
     for d in ['codemirror', 'jslibs']:

+ 11 - 12
src/eberon/eberon_grammar.js

@@ -11,38 +11,36 @@ var optional = Parser.optional;
 var or = Parser.or;
 var or = Parser.or;
 var repeat = Parser.repeat;
 var repeat = Parser.repeat;
 
 
-var ident = Grammar.ident;
-
-function makeProcedureHeading(formalParameters){
+function makeProcedureHeading(ident, identdef, formalParameters){
     return and("PROCEDURE",
     return and("PROCEDURE",
-               context(and(optional(and(ident, ".")), Grammar.identdef), EbContext.ProcOrMethodId),
+               context(and(optional(and(ident, ".")), identdef), EbContext.ProcOrMethodId),
                context(optional(formalParameters), Context.FormalParametersProcDecl)
                context(optional(formalParameters), Context.FormalParametersProcDecl)
                );
                );
 }
 }
 
 
-function makeDesignator(selector){
+function makeDesignator(qualident, selector){
     return context(
     return context(
-        and(or("SELF", "SUPER", Grammar.qualident), repeat(selector)), EbContext.Designator);
+        and(or("SELF", "SUPER", qualident), repeat(selector)), EbContext.Designator);
 }
 }
 
 
-function makeProcedureDeclaration(procedureHeading, procedureBody){
+function makeProcedureDeclaration(ident, procedureHeading, procedureBody){
     return context(and(procedureHeading, ";",
     return context(and(procedureHeading, ";",
                        procedureBody,
                        procedureBody,
                        and(ident, optional(and(".", ident)))),
                        and(ident, optional(and(".", ident)))),
                    EbContext.ProcOrMethodDecl);
                    EbContext.ProcOrMethodDecl);
 }
 }
 
 
-function makeMethodHeading(formalParameters){
+function makeMethodHeading(identdef, formalParameters){
     return context(
     return context(
         and("PROCEDURE",
         and("PROCEDURE",
-            Grammar.identdef,
+            identdef,
             context(optional(formalParameters), Context.FormalParametersProcDecl)),
             context(optional(formalParameters), Context.FormalParametersProcDecl)),
         EbContext.MethodHeading);
         EbContext.MethodHeading);
 }
 }
 
 
-function makeFieldList(identList, type, formalParameters){
+function makeFieldList(identdef, identList, type, formalParameters){
     return context(
     return context(
-        or(makeMethodHeading(formalParameters),
+        or(makeMethodHeading(identdef, formalParameters),
            and(identList, ":", type)),
            and(identList, ":", type)),
         Context.FieldListDeclaration);
         Context.FieldListDeclaration);
 }
 }
@@ -52,5 +50,6 @@ exports.grammar = Grammar.make(
     makeProcedureHeading,
     makeProcedureHeading,
     makeProcedureDeclaration,
     makeProcedureDeclaration,
     makeFieldList,
     makeFieldList,
-    EbContext.RecordDecl
+    EbContext.RecordDecl,
+    Grammar.reservedWords + " SELF SUPER"
     );
     );

+ 18 - 11
src/grammar.js

@@ -8,7 +8,6 @@ var Class = require("rtl.js").Class;
 var literal = Parser.literal;
 var literal = Parser.literal;
 var digit = Lexer.digit;
 var digit = Lexer.digit;
 var hexDigit = Lexer.hexDigit;
 var hexDigit = Lexer.hexDigit;
-var ident = Lexer.ident;
 var point = Lexer.point;
 var point = Lexer.point;
 var separator = Lexer.separator;
 var separator = Lexer.separator;
 
 
@@ -21,26 +20,33 @@ var context = Parser.context;
 var emit = Parser.emit;
 var emit = Parser.emit;
 var required = Parser.required;
 var required = Parser.required;
 
 
-var qualident = context(and(optional(and(ident, ".")), ident),
-                        Context.QualifiedIdentificator);
-var identdef = context(and(ident, optional("*")),
-                       Context.Identdef);
+var reservedWords = "ARRAY IMPORT THEN BEGIN IN TO BY IS TRUE CASE MOD TYPE CONST MODULE UNTIL DIV NIL VAR DO OF WHILE ELSE OR ELSIF POINTER END PROCEDURE FALSE RECORD FOR REPEAT IF RETURN";
 
 
 function make(makeDesignator,
 function make(makeDesignator,
               makeProcedureHeading, 
               makeProcedureHeading, 
               makeProcedureDeclaration,
               makeProcedureDeclaration,
               makeFieldList,
               makeFieldList,
-              recordDeclContext
+              recordDeclContext,
+              reservedWords
               ){
               ){
 var result = {};
 var result = {};
 
 
+var ident = function(stream, context){
+    return Lexer.ident(stream, context, reservedWords);
+};
+
+var qualident = context(and(optional(and(ident, ".")), ident),
+                        Context.QualifiedIdentificator);
+var identdef = context(and(ident, optional("*")),
+                       Context.Identdef);
+
 var selector = or(and(point, ident)
 var selector = or(and(point, ident)
                 // break recursive declaration of expList
                 // break recursive declaration of expList
                 , and("[", function(stream, context){return expList(stream, context);}, "]")
                 , and("[", function(stream, context){return expList(stream, context);}, "]")
                 , "^"
                 , "^"
                 , context(and("(", qualident, ")"), Context.TypeCast)
                 , context(and("(", qualident, ")"), Context.TypeCast)
                 );
                 );
-var designator = makeDesignator(selector);
+var designator = makeDesignator(qualident, selector);
 var type = or(context(qualident, Context.Type),
 var type = or(context(qualident, Context.Type),
               function(stream, context){return strucType(stream, context);} // break recursive declaration of strucType
               function(stream, context){return strucType(stream, context);} // break recursive declaration of strucType
              );
              );
@@ -139,6 +145,7 @@ var forStatement = context(and("FOR", ident, ":=", expression, "TO", expression
                          , Context.For);
                          , Context.For);
 
 
 var fieldList = makeFieldList(
 var fieldList = makeFieldList(
+        identdef,
         identList,
         identList,
         type,
         type,
         function(stream, context){return formalParameters(stream, context);}
         function(stream, context){return formalParameters(stream, context);}
@@ -179,10 +186,12 @@ result.expression = expression;
 result.statement = statement;
 result.statement = statement;
 result.typeDeclaration = typeDeclaration;
 result.typeDeclaration = typeDeclaration;
 result.variableDeclaration = variableDeclaration;
 result.variableDeclaration = variableDeclaration;
-var procedureHeading = makeProcedureHeading(formalParameters);
+var procedureHeading = makeProcedureHeading(ident, identdef, formalParameters);
+result.ident = ident;
 result.procedureDeclaration
 result.procedureDeclaration
     // break recursive declaration of procedureBody
     // break recursive declaration of procedureBody
     = makeProcedureDeclaration(
     = makeProcedureDeclaration(
+        ident,
         procedureHeading,
         procedureHeading,
         function(stream, context){
         function(stream, context){
             return result.procedureBody(stream, context);}
             return result.procedureBody(stream, context);}
@@ -208,6 +217,4 @@ return result;
 }
 }
 
 
 exports.make = make;
 exports.make = make;
-exports.ident = ident;
-exports.identdef = identdef;
-exports.qualident = qualident;
+exports.reservedWords = reservedWords;

+ 4 - 5
src/js/Lexer.js

@@ -1,12 +1,11 @@
 var RTL$ = require("rtl.js");
 var RTL$ = require("rtl.js");
 var JS = GLOBAL;
 var JS = GLOBAL;
-var JsString = require("js/JsString.js");
-var Errors = require("js/Errors.js");
-var Stream = require("js/Stream.js");
+var JsString = require("JsString.js");
+var Errors = require("Errors.js");
+var Stream = require("Stream.js");
 var quote = "\"";
 var quote = "\"";
 var commentBegin = "(*";
 var commentBegin = "(*";
 var commentEnd = "*)";
 var commentEnd = "*)";
-var reservedWords = "ARRAY IMPORT THEN BEGIN IN TO BY IS TRUE CASE MOD TYPE CONST MODULE UNTIL DIV NIL VAR DO OF WHILE ELSE OR ELSIF POINTER END PROCEDURE FALSE RECORD FOR REPEAT IF RETURN";
 var jsReservedWords = "break case catch continue debugger default delete do else finally for function if in instanceof new return switch this throw try typeof var void while with Math";
 var jsReservedWords = "break case catch continue debugger default delete do else finally for function if in instanceof new return switch this throw try typeof var void while with Math";
 var Context = RTL$.extend({
 var Context = RTL$.extend({
 	init: function Context(){
 	init: function Context(){
@@ -113,7 +112,7 @@ function isReservedWorld(s/*Type*/, words/*ARRAY OF CHAR*/){
 	return i == JsString.len(s);
 	return i == JsString.len(s);
 }
 }
 
 
-function ident(stream/*Type*/, context/*Context*/){
+function ident(stream/*Type*/, context/*Context*/, reservedWords/*ARRAY OF CHAR*/){
 	var result = false;
 	var result = false;
 	var c = 0;
 	var c = 0;
 	var s = null;
 	var s = null;

+ 1 - 2
src/ob/Lexer.ob

@@ -5,7 +5,6 @@ CONST
     quote = 22X; (* " *)
     quote = 22X; (* " *)
     commentBegin = "(*";
     commentBegin = "(*";
     commentEnd = "*)";
     commentEnd = "*)";
-    reservedWords = "ARRAY IMPORT THEN BEGIN IN TO BY IS TRUE CASE MOD TYPE CONST MODULE UNTIL DIV NIL VAR DO OF WHILE ELSE OR ELSIF POINTER END PROCEDURE FALSE RECORD FOR REPEAT IF RETURN";
     jsReservedWords = "break case catch continue debugger default delete do else finally for function if in instanceof new return switch this throw try typeof var void while with Math"; (* Math is used in generated code for some functions so it is reserved word from code generator standpoint *)
     jsReservedWords = "break case catch continue debugger default delete do else finally for function if in instanceof new return switch this throw try typeof var void while with Math"; (* Math is used in generated code for some functions so it is reserved word from code generator standpoint *)
 
 
 TYPE
 TYPE
@@ -123,7 +122,7 @@ BEGIN
     RETURN i = JsString.len(s)
     RETURN i = JsString.len(s)
 END isReservedWorld;
 END isReservedWorld;
 
 
-PROCEDURE ident*(stream: Stream.Type; context: Context): BOOLEAN;
+PROCEDURE ident*(stream: Stream.Type; context: Context; reservedWords: ARRAY OF CHAR): BOOLEAN;
 VAR
 VAR
     result: BOOLEAN;
     result: BOOLEAN;
     c: CHAR;
     c: CHAR;

+ 88 - 5
src/ob/Types.ob

@@ -3,15 +3,98 @@ IMPORT JsString;
 
 
 TYPE
 TYPE
     Id = RECORD END;
     Id = RECORD END;
-    Type = POINTER TO RECORD(Id)
+    
+    Type = RECORD(Id)
+        PROCEDURE idType(): JsString.Type;
         PROCEDURE description(): JsString.Type
         PROCEDURE description(): JsString.Type
     END;
     END;
+    PType = POINTER TO Type;
+    
     TypeId = RECORD(Id)
     TypeId = RECORD(Id)
-        type: Type
+        PROCEDURE type(): PType;
+        PROCEDURE description(): JsString.Type;
+        PROCEDURE strip();
+
+        mType: PType
+    END;
+
+    ResolveTypeCallback = PROCEDURE(): PType;
+
+    ForwardTypeId = RECORD(TypeId)
+        resolve: ResolveTypeCallback
+    END;
+
+    LazyTypeId = RECORD(TypeId)
+    END;
+
+    String = RECORD(Type)
+        s: JsString.Type
+    END;
+
+    Record = RECORD(Type) END;
+    
+    NonExportedRecord = RECORD(Record) END;
+    PNonExportedRecord = POINTER TO NonExportedRecord;
+
+PROCEDURE TypeId.description(): JsString.Type;
+VAR
+    t: PType;
+BEGIN
+    t := SELF.type()
+    RETURN JsString.concat(JsString.make("type "), t.description())
+END TypeId.description;
+
+PROCEDURE makeNonExportedRecord(): PNonExportedRecord;
+VAR
+    result: PNonExportedRecord;
+BEGIN
+    NEW(result);
+    RETURN result
+END makeNonExportedRecord;    
+
+PROCEDURE TypeId.strip();
+BEGIN
+    IF SELF.mType IS Record THEN
+        SELF.mType := makeNonExportedRecord();
+    ELSE
+        SELF.mType := NIL;
+    END;
+END TypeId.strip;
+
+PROCEDURE makeForwardTypeId(p: ResolveTypeCallback);
+END makeForwardTypeId;
+
+PROCEDURE ForwardTypeId.type(): PType;
+BEGIN
+    IF SELF.mType = NIL THEN
+        SELF.mType := SELF.resolve();
+    END;
+    RETURN SELF.mType
+END ForwardTypeId.type;
+
+PROCEDURE defineTypeId(VAR tId: LazyTypeId; t: PType);
+BEGIN
+    tId.mType := t;
+END defineTypeId;
+
+PROCEDURE String.idType(): JsString.Type;
+    RETURN JsString.make("string")
+END String.idType;
+
+PROCEDURE String.description(): JsString.Type;
+VAR
+    prefix: JsString.Type;
+BEGIN
+    IF JsString.len(SELF.s) = 1 THEN
+        prefix := JsString.make("single-");
+    ELSE
+        prefix := JsString.make("multi-");
     END;
     END;
+    RETURN JsString.concat(prefix, JsString.make("character string"))
+END String.description;
 
 
-PROCEDURE description*(t: TypeId): JsString.Type;
-    RETURN JsString.concat(JsString.make("type "), t.type.description())
-END description;
+PROCEDURE stringValue(s: String): JsString.Type;
+    RETURN s.s
+END stringValue
 
 
 END Types.
 END Types.

+ 9 - 8
src/oberon/oberon_grammar.js

@@ -10,24 +10,24 @@ var context = Parser.context;
 var optional = Parser.optional;
 var optional = Parser.optional;
 var repeat = Parser.repeat;
 var repeat = Parser.repeat;
 
 
-function makeProcedureHeading(formalParameters){
+function makeProcedureHeading(ident, identdef, formalParameters){
     return and("PROCEDURE"
     return and("PROCEDURE"
-             , Grammar.identdef
+             , identdef
              , context(optional(formalParameters), Context.FormalParametersProcDecl));
              , context(optional(formalParameters), Context.FormalParametersProcDecl));
 }
 }
 
 
-function makeDesignator(selector){
-    return context(and(Grammar.qualident, repeat(selector)), Context.Designator);
+function makeDesignator(qualident, selector){
+    return context(and(qualident, repeat(selector)), Context.Designator);
 }
 }
 
 
-function makeProcedureDeclaration(procedureHeading, procedureBody){
+function makeProcedureDeclaration(ident, procedureHeading, procedureBody){
     return context(and(procedureHeading, ";",
     return context(and(procedureHeading, ";",
                        procedureBody,
                        procedureBody,
-                       Grammar.ident),
+                       ident),
                    Context.ProcDecl);
                    Context.ProcDecl);
 }
 }
 
 
-function makeFieldList(identList, type){
+function makeFieldList(identdef, identList, type){
     return context(and(identList, ":", type), Context.FieldListDeclaration);
     return context(and(identList, ":", type), Context.FieldListDeclaration);
 }
 }
 
 
@@ -36,5 +36,6 @@ exports.grammar = Grammar.make(
     makeProcedureHeading,
     makeProcedureHeading,
     makeProcedureDeclaration,
     makeProcedureDeclaration,
     makeFieldList,
     makeFieldList,
-    ObContext.RecordDecl
+    ObContext.RecordDecl,
+    Grammar.reservedWords
     );
     );

+ 14 - 0
test/1.py

@@ -0,0 +1,14 @@
+i = 3
+
+def f1():
+	i = 1
+	def f2():
+		global i
+		i = 2
+		print(i)
+
+	f2()
+	print(i)
+
+f1()
+print(i)

+ 2 - 0
test/make_snapshot.cmd

@@ -2,6 +2,8 @@ del /S /Q ..\snapshot
 mkdir ..\snapshot
 mkdir ..\snapshot
 mkdir ..\snapshot\eberon
 mkdir ..\snapshot\eberon
 mkdir ..\snapshot\oberon
 mkdir ..\snapshot\oberon
+mkdir ..\snapshot\js
 copy ..\src\*.js ..\snapshot
 copy ..\src\*.js ..\snapshot
 copy ..\src\eberon\*.js ..\snapshot\eberon
 copy ..\src\eberon\*.js ..\snapshot\eberon
 copy ..\src\oberon\*.js ..\snapshot\oberon
 copy ..\src\oberon\*.js ..\snapshot\oberon
+copy ..\src\js\*.js ..\snapshot\js

+ 1 - 1
test/test_compile.cmd

@@ -1,2 +1,2 @@
-SET NODE_PATH=.;%~dp0../src;%~dp0../src/oberon.js
+SET NODE_PATH=.;%~dp0../src;%~dp0../src/js
 "C:\Program Files\nodejs\node.exe" test_compile.js %*
 "C:\Program Files\nodejs\node.exe" test_compile.js %*

+ 1 - 1
test/test_unit.js

@@ -101,7 +101,7 @@ return {
         });
         });
         function makeContext() {return new IdentDeclarationContext();}
         function makeContext() {return new IdentDeclarationContext();}
 
 
-        return setupParser(Grammar.ident, makeContext);},
+        return setupParser(grammar.ident, makeContext);},
     pass("i", "abc1"),
     pass("i", "abc1"),
     fail(["", "not parsed"],
     fail(["", "not parsed"],
          [";", "not parsed"],
          [";", "not parsed"],

+ 11 - 2
test/test_unit_eberon.js

@@ -16,6 +16,12 @@ function testWithModule(src, pass, fail){
 }
 }
 
 
 exports.suite = {
 exports.suite = {
+"key words": TestUnitCommon.testWithGrammar(
+    grammar.variableDeclaration,
+    pass(),
+    fail(["SELF: INTEGER", "not parsed"],
+         ["SUPER: INTEGER", "not parsed"])
+    ),
 "abstract method declaration": testWithContext(
 "abstract method declaration": testWithContext(
     context(grammar.declarationSequence, 
     context(grammar.declarationSequence, 
             "TYPE T = RECORD PROCEDURE p() END;"
             "TYPE T = RECORD PROCEDURE p() END;"
@@ -75,8 +81,11 @@ exports.suite = {
     ),
     ),
 "SELF": testWithContext(
 "SELF": testWithContext(
     context(grammar.declarationSequence,
     context(grammar.declarationSequence,
-            "TYPE T = RECORD PROCEDURE p(); i: INTEGER END;"),
-    pass("PROCEDURE T.p(); BEGIN SELF.i := 0; END T.p;"),
+              "TYPE T = RECORD PROCEDURE p(); i: INTEGER END;"
+            + "PROCEDURE proc(i: INTEGER); END proc;"),
+    pass("PROCEDURE T.p(); BEGIN SELF.i := 0; END T.p;",
+         "PROCEDURE T.p(); BEGIN proc(SELF.i); END T.p;"
+         ),
     fail(["PROCEDURE p(); BEGIN SELF.i := 0; END p;",
     fail(["PROCEDURE p(); BEGIN SELF.i := 0; END p;",
           "SELF can be used only in methods"])
           "SELF can be used only in methods"])
     ),
     ),