Parcourir la source

SELF and SUPER are keywords for Eberon

Vladislav Folts il y a 11 ans
Parent
commit
234ae17d07

+ 1 - 1
build.py

@@ -76,7 +76,7 @@ def build(out, use_git):
 
     link(['oc.js', 'oberon/oberon_grammar.js', 'eberon/eberon_grammar.js'],
          os.path.join(out, 'oc.js'),
-         ['src', 'src/oberon.js'],
+         ['src', 'src/js'],
          version)
     copy('browser/oberonjs.html', out)
     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 repeat = Parser.repeat;
 
-var ident = Grammar.ident;
-
-function makeProcedureHeading(formalParameters){
+function makeProcedureHeading(ident, identdef, formalParameters){
     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)
                );
 }
 
-function makeDesignator(selector){
+function makeDesignator(qualident, selector){
     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, ";",
                        procedureBody,
                        and(ident, optional(and(".", ident)))),
                    EbContext.ProcOrMethodDecl);
 }
 
-function makeMethodHeading(formalParameters){
+function makeMethodHeading(identdef, formalParameters){
     return context(
         and("PROCEDURE",
-            Grammar.identdef,
+            identdef,
             context(optional(formalParameters), Context.FormalParametersProcDecl)),
         EbContext.MethodHeading);
 }
 
-function makeFieldList(identList, type, formalParameters){
+function makeFieldList(identdef, identList, type, formalParameters){
     return context(
-        or(makeMethodHeading(formalParameters),
+        or(makeMethodHeading(identdef, formalParameters),
            and(identList, ":", type)),
         Context.FieldListDeclaration);
 }
@@ -52,5 +50,6 @@ exports.grammar = Grammar.make(
     makeProcedureHeading,
     makeProcedureDeclaration,
     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 digit = Lexer.digit;
 var hexDigit = Lexer.hexDigit;
-var ident = Lexer.ident;
 var point = Lexer.point;
 var separator = Lexer.separator;
 
@@ -21,26 +20,33 @@ var context = Parser.context;
 var emit = Parser.emit;
 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,
               makeProcedureHeading, 
               makeProcedureDeclaration,
               makeFieldList,
-              recordDeclContext
+              recordDeclContext,
+              reservedWords
               ){
 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)
                 // break recursive declaration of expList
                 , and("[", function(stream, context){return expList(stream, context);}, "]")
                 , "^"
                 , context(and("(", qualident, ")"), Context.TypeCast)
                 );
-var designator = makeDesignator(selector);
+var designator = makeDesignator(qualident, selector);
 var type = or(context(qualident, Context.Type),
               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);
 
 var fieldList = makeFieldList(
+        identdef,
         identList,
         type,
         function(stream, context){return formalParameters(stream, context);}
@@ -179,10 +186,12 @@ result.expression = expression;
 result.statement = statement;
 result.typeDeclaration = typeDeclaration;
 result.variableDeclaration = variableDeclaration;
-var procedureHeading = makeProcedureHeading(formalParameters);
+var procedureHeading = makeProcedureHeading(ident, identdef, formalParameters);
+result.ident = ident;
 result.procedureDeclaration
     // break recursive declaration of procedureBody
     = makeProcedureDeclaration(
+        ident,
         procedureHeading,
         function(stream, context){
             return result.procedureBody(stream, context);}
@@ -208,6 +217,4 @@ return result;
 }
 
 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 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 commentBegin = "(*";
 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 Context = RTL$.extend({
 	init: function Context(){
@@ -113,7 +112,7 @@ function isReservedWorld(s/*Type*/, words/*ARRAY OF CHAR*/){
 	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 c = 0;
 	var s = null;

+ 1 - 2
src/ob/Lexer.ob

@@ -5,7 +5,6 @@ CONST
     quote = 22X; (* " *)
     commentBegin = "(*";
     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 *)
 
 TYPE
@@ -123,7 +122,7 @@ BEGIN
     RETURN i = JsString.len(s)
 END isReservedWorld;
 
-PROCEDURE ident*(stream: Stream.Type; context: Context): BOOLEAN;
+PROCEDURE ident*(stream: Stream.Type; context: Context; reservedWords: ARRAY OF CHAR): BOOLEAN;
 VAR
     result: BOOLEAN;
     c: CHAR;

+ 88 - 5
src/ob/Types.ob

@@ -3,15 +3,98 @@ IMPORT JsString;
 
 TYPE
     Id = RECORD END;
-    Type = POINTER TO RECORD(Id)
+    
+    Type = RECORD(Id)
+        PROCEDURE idType(): JsString.Type;
         PROCEDURE description(): JsString.Type
     END;
+    PType = POINTER TO Type;
+    
     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;
+    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.

+ 9 - 8
src/oberon/oberon_grammar.js

@@ -10,24 +10,24 @@ var context = Parser.context;
 var optional = Parser.optional;
 var repeat = Parser.repeat;
 
-function makeProcedureHeading(formalParameters){
+function makeProcedureHeading(ident, identdef, formalParameters){
     return and("PROCEDURE"
-             , Grammar.identdef
+             , identdef
              , 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, ";",
                        procedureBody,
-                       Grammar.ident),
+                       ident),
                    Context.ProcDecl);
 }
 
-function makeFieldList(identList, type){
+function makeFieldList(identdef, identList, type){
     return context(and(identList, ":", type), Context.FieldListDeclaration);
 }
 
@@ -36,5 +36,6 @@ exports.grammar = Grammar.make(
     makeProcedureHeading,
     makeProcedureDeclaration,
     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\eberon
 mkdir ..\snapshot\oberon
+mkdir ..\snapshot\js
 copy ..\src\*.js ..\snapshot
 copy ..\src\eberon\*.js ..\snapshot\eberon
 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 %*

+ 1 - 1
test/test_unit.js

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

+ 11 - 2
test/test_unit_eberon.js

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