From bc96e8ce03bb419fc46d9f024d126ee7f2eaf907 Mon Sep 17 00:00:00 2001 From: Jerome St-Louis Date: Mon, 8 Jul 2013 03:35:27 -0400 Subject: [PATCH 1/1] compiler/libec2: Support for class value initializers, error recovery before initializers (#910) --- compiler/libec2/src/astNode.ec | 5 +- compiler/libec2/src/classes.ec | 184 +++++++++++++++++++++++++------------ compiler/libec2/src/declarators.ec | 70 ++++++++++---- compiler/libec2/src/expressions.ec | 113 +++++++++++++---------- compiler/libec2/src/externals.ec | 34 +++++-- compiler/libec2/src/lexing.ec | 2 +- compiler/libec2/src/specifiers.ec | 113 ++++++++++++++--------- compiler/libec2/src/statements.ec | 36 ++++---- compiler/libec2/test.ec | 23 +++-- 9 files changed, 371 insertions(+), 209 deletions(-) diff --git a/compiler/libec2/src/astNode.ec b/compiler/libec2/src/astNode.ec index 53747fb..798bfd4 100644 --- a/compiler/libec2/src/astNode.ec +++ b/compiler/libec2/src/astNode.ec @@ -59,9 +59,10 @@ public: if(!list) list = eInstance_New(c); list.Add(e); } - if(sep && peekToken().type == sep) + peekToken(); + if(sep && nextToken.type == sep) readToken(); - else if(sep || peekToken().type == '}') + else if(sep || nextToken.type == '}' || !nextToken.type) break; } return list; diff --git a/compiler/libec2/src/classes.ec b/compiler/libec2/src/classes.ec index 3e8f263..4fe8b2b 100644 --- a/compiler/libec2/src/classes.ec +++ b/compiler/libec2/src/classes.ec @@ -1,71 +1,80 @@ import "externals" -/* -public class MembersInit : struct +public class ASTMemberInit : ASTNode { public: - MembersInit prev, next; - Location loc; - MembersInitType type; - union - { - OldList * dataMembers; - ClassFunction function; - }; - //bool coloned; -}; - -public class MemberInit : struct -{ -public: - MemberInit prev, next; - Location loc; Location realLoc; - OldList * identifiers; - // Expression exp; - Initializer initializer; + List identifiers; + ASTInitializer initializer; // COMPILE DATA bool used; bool variable; bool takeOutExp; + + ASTMemberInit ::parse() + { + ASTMemberInit init { }; + while(true) + { + ASTIdentifier id = ASTIdentifier::parse(); + if(id) + { + if(!init.identifiers) init.identifiers = { }; + init.identifiers.Add(id); + if(peekToken().type != '.') + break; + } + } + if(peekToken().type == '=') + { + readToken(); + init.initializer = ASTInitializer::parse(); + } + return init; + } + + void print() + { + if(identifiers) + { + Iterator it { identifiers }; + while(it.Next()) + { + it.data.print(); + if(identifiers.GetNext(it.pointer)) + Print("."); + } + } + Print(" = "); + if(initializer) initializer.print(); + } }; -*/ -/* -public class ASTClassDefinition : struct +public class MemberInitList : ASTList { -public: - ASTSpecifier _class; - SpecsList baseSpecs; - SpecsList definitions; - Symbol symbol; - Location blockStart; - Location nameLoc; - int endid; - AccessMode declMode; - bool deleteWatchable; -}; -*/ + MemberInitList ::parse() + { + MemberInitList list = (MemberInitList)ASTList::parse(class(MemberInitList), ASTMemberInit::parse, ','); + if(peekToken().type == ';') + readToken(); + return list; + } +} -/* -public class PropertyDef : struct +public class ASTPropertyDef : ASTNode { -public: - PropertyDef prev, next; - Location loc; - OldList * specifiers; + SpecsList specifiers; ASTDeclarator declarator; - Identifier id; - Statement getStmt; - Statement setStmt; - Statement issetStmt; + ASTIdentifier id; + ASTStatement getStmt; + ASTStatement setStmt; + ASTStatement issetStmt; Symbol symbol; bool conversion; bool isWatchable; - Expression category; + ASTExpression category; }; -*/ public class ClassDefList : ASTList { @@ -76,7 +85,6 @@ public class ClassDefList : ASTList void printSep() { - PrintLn(""); } } @@ -90,18 +98,38 @@ public: ASTClassDef ::parse() { - SpecsList specs = SpecsList::parse(); - InitDeclList decls = InitDeclList::parse(); + SpecsList specs = null; + InitDeclList decls = null; + int a = -1; + + peekToken(); + if(nextToken.type == '}') + return null; + + if(nextToken.type == IDENTIFIER) + a = pushAmbiguity(); - if(peekToken().type == '{') + specs = SpecsList::parse(); + decls = InitDeclList::parse(); + peekToken(); + if(nextToken.type == '{' || (decls && decls[0] && decls[0].declarator && decls[0].declarator._class == class(DeclFunction))) return ClassDefFunction::parse(specs, decls); - else if(specs || decls) + else if((specs || decls) && (nextToken.type != '.' && nextToken.type != '=')) + { + if(a > -1) clearAmbiguity(); return ClassDefDeclaration::parse(specs, decls); - else + } + else if(a > -1) { - readToken(); // Error - return null; + ClassDefInitialization init; + popAmbiguity(a); + + init = ClassDefInitialization::parse(); + if(init) + return init; } + readToken(); // Error + return null; } }; @@ -129,6 +157,7 @@ public class ClassDefDeclaration : ASTClassDef { printIndent(); if(decl) decl.print(); + PrintLn(""); } } @@ -162,9 +191,7 @@ public class ClassDefFunction : ASTClassDef { ASTClassFunction function = ASTClassFunction::parse(specs, decls); if(function) - { return { function = function }; - } return null; } @@ -174,10 +201,45 @@ public class ClassDefFunction : ASTClassDef } } -/* - List defProperties; +public class ClassDefInitialization : ASTClassDef +{ + MemberInitList defValues; + + ClassDefInitialization ::parse() + { + MemberInitList defValues = MemberInitList::parse(); + if(defValues) + return { defValues = defValues }; + return null; + } + + void print() + { + if(defValues) + { + printIndent(); + defValues.print(); + PrintLn(";"); + } + } +} + +public class ClassDefProperty : ASTClassDef +{ ASTPropertyDef propertyDef; +} + +public class ClassDefPropertyWatch : ASTClassDef +{ ASTPropertyWatch propertyWatch; +} + +public class ClassDefDesigner : ASTClassDef +{ String designer; +} + +public class ClassDefDefaultProperty : ASTClassDef +{ ASTIdentifier defaultProperty; -*/ +} diff --git a/compiler/libec2/src/declarators.ec b/compiler/libec2/src/declarators.ec index 867c8ca..66a3284 100644 --- a/compiler/libec2/src/declarators.ec +++ b/compiler/libec2/src/declarators.ec @@ -10,7 +10,7 @@ public class ASTPointer : ASTNode Print("*"); if(qualifiers) qualifiers.print(); if(pointer) pointer.print(); - } + } ASTPointer ::parse() { @@ -60,6 +60,43 @@ public: } } +public class TypeNameList : ASTList +{ + TypeNameList ::parse() + { + TypeNameList list = null; + int a = pushAmbiguity(); + while(true) + { + ASTTypeName e = ASTTypeName::parse(); + peekToken(); + if(e && (nextToken.type == ',' || nextToken.type == ')')) + { + if(!list) list = { }; + list.Add(e); + + clearAmbiguity(); + if(nextToken.type == ',') + { + readToken(); + a = pushAmbiguity(); + } + else + break; + } + else + { + if(list) + list.Add({}); + popAmbiguity(a); + break; + } + } + return list; + // return (TypeNameList)ASTList::parse(class(TypeNameList), ASTTypeName::parse, ','); + } +} + public class DeclFunction : ASTDeclarator { public: @@ -79,7 +116,8 @@ public: DeclFunction decl { declarator = d }; readToken(); if(peekToken().type != ')') decl.parameters = TypeNameList::parse(); - if(peekToken().type == ')') readToken(); + if(peekToken().type == ')') + readToken(); return decl; } } @@ -106,7 +144,7 @@ public class DeclBrackets : ASTDeclarator void print() { Print("("); - if(declarator) declarator.print(); + if(declarator) declarator.print(); Print(")"); } @@ -132,9 +170,9 @@ public class DeclArray : ASTDeclarator void print() { - if(declarator) declarator.print(); + if(declarator) declarator.print(); Print("["); - if(exp) exp.print(); + if(exp) exp.print(); Print("]"); } @@ -168,9 +206,9 @@ public class DeclPointer : ASTDeclarator public class DeclStruct : ASTDeclarator { ASTDeclarator declarator; - Expression exp; - Expression posExp; - Attrib attrib; + ASTExpression exp; + ASTExpression posExp; + ASTAttrib attrib; DeclStruct ::parse() { @@ -178,18 +216,10 @@ public class DeclStruct : ASTDeclarator } } -/* - union - { - struct - { - } structDecl; - struct - { - ExtDecl extended; - } extended; - }; -*/ +public class DeclExtended : ASTDeclarator +{ + ExtDecl extended; +} public class ASTInitializer : ASTNode { diff --git a/compiler/libec2/src/expressions.ec b/compiler/libec2/src/expressions.ec index b82ea47..5973da0 100644 --- a/compiler/libec2/src/expressions.ec +++ b/compiler/libec2/src/expressions.ec @@ -69,7 +69,9 @@ public: { SpecsList specs = SpecsList::parse(); ASTDeclarator decl = ASTDeclarator::parse(); - return { qualifiers = specs, declarator = decl }; + if(specs || decl) + return { qualifiers = specs, declarator = decl }; + return null; } void print() @@ -79,14 +81,6 @@ public: } }; -public class TypeNameList : ASTList -{ - TypeNameList ::parse() - { - return (TypeNameList)ASTList::parse(class(TypeNameList), ASTTypeName::parse, ','); - } -} - // Expressions public class ASTExpression : ASTNode { @@ -140,11 +134,11 @@ public: */ } -public class ListExp : ASTList +public class ExpList : ASTList { - ListExp ::parse() + ExpList ::parse() { - return (ListExp)ASTList::parse(class(ListExp), ASTExpression::parse, ','); + return (ExpList)ASTList::parse(class(ExpList), ASTExpression::parse, ','); } } @@ -212,7 +206,7 @@ static ASTExpression parsePrimaryExpression() { ExpBrackets exp { }; readToken(); - exp.list = ListExp::parse(); + exp.list = ExpList::parse(); if(peekToken().type == ')') readToken(); return exp; @@ -258,16 +252,12 @@ static ASTExpression parseUnaryExpression() readToken(); return ExpOperation { op = token.type, exp2 = ExpCast::parse() }; } - /*else if(nextToken == SIZEOF) - { - readToken(); - return ExpSizeof { }; - } - else if(nextToken == ALIGNOF) - { - readToken(); - return ExpSizeof { }; - }*/ + /* + else if(nextToken.type == SIZEOF) + return ExpSizeof::parse(); + else if(nextToken.type == ALIGNOF) + return ExpAlignOf::parse(); + */ else return parsePostfixExpression(); } @@ -380,7 +370,7 @@ public class ExpAssignment : ExpOperation public class ExpBrackets : ASTExpression { public: - ListExp list; + ExpList list; void print() { @@ -399,7 +389,7 @@ public class ExpConditional : ASTExpression { public: ASTExpression condition; - ListExp expList; + ExpList expList; ASTExpression elseExp; void print() @@ -417,7 +407,7 @@ public: ASTExpression exp = ExpOperation::parse(numPrec-1); if(peekToken().type == '?') { - exp = ExpConditional { condition = exp, expList = ListExp::parse() }; + exp = ExpConditional { condition = exp, expList = ExpList::parse() }; if(peekToken().type == ':') ((ExpConditional)exp).elseExp = ExpConditional::parse(); } @@ -428,7 +418,7 @@ public: public class ExpIndex : ASTExpression { ASTExpression exp; - ListExp index; + ExpList index; void print() { @@ -442,7 +432,7 @@ public class ExpIndex : ASTExpression { ExpIndex exp; readToken(); - exp = ExpIndex { exp = e, index = ListExp::parse() }; + exp = ExpIndex { exp = e, index = ExpList::parse() }; if(peekToken().type == ']') readToken(); return exp; @@ -491,7 +481,7 @@ public class ExpPointer : ExpMember public class ExpCall : ASTExpression { ASTExpression exp; - ListExp arguments; + ExpList arguments; // Location argLoc; void print() @@ -506,7 +496,7 @@ public class ExpCall : ASTExpression { ExpCall exp; readToken(); - exp = ExpCall { exp = e, arguments = ListExp::parse() }; + exp = ExpCall { exp = e, arguments = ExpList::parse() }; if(peekToken().type == ')') readToken(); return exp; @@ -526,9 +516,33 @@ public class ExpCast : ASTExpression } } -/* union +public class ExpInstance : ASTExpression +{ + ASTInstantiation instance; +} +/* +public class ExpSizeOf : ASTExpression +{ + ASTTypeName typeName; + + ExpSizeOf ::parse() + { + + } +} + +public class ExpAlignOf : ASTExpression +{ + ASTTypeName typeName; + + ExpAlignOf ::parse() + { + } +} +*/ +/* + union { - Instantiation instance; struct { OldList * specifiers; @@ -575,26 +589,24 @@ public class ExpCast : ASTExpression }; */ -/* - Instantiation inst; - struct - { - Identifier id; - Expression exp; - }; - Specifier extStorage; - Symbol symbol; - AccessMode declMode; -*/ -/* -public class Instantiation : struct +public class InstanceInit : ASTNode { } + +public class InstInitMember : InstanceInit +{ + MemberInitList members; +} + +public class InstInitFunction : InstanceInit +{ + ASTClassFunction function; +} + +public class ASTInstantiation : ASTNode { public: - Instantiation prev, next; - Location loc; - Specifier _class; - Expression exp; - OldList * members; + ASTSpecifier _class; + ASTExpression exp; + List members; Symbol symbol; bool fullSet; bool isConstant; @@ -602,4 +614,3 @@ public: Location nameLoc, insideLoc; bool built; }; -*/ diff --git a/compiler/libec2/src/externals.ec b/compiler/libec2/src/externals.ec index f53f3f1..e2e9819 100644 --- a/compiler/libec2/src/externals.ec +++ b/compiler/libec2/src/externals.ec @@ -4,6 +4,9 @@ public class ASTDeclaration : ASTStmtOrDecl { public: DeclarationType type; + // ASTSpecifier extStorage; + // Symbol symbol; + // AccessMode declMode; ASTDeclaration ::parse(SpecsList specs, InitDeclList decls) { @@ -31,6 +34,17 @@ public: } } +public class DeclarationInstance : ASTDeclaration +{ + ASTInstantiation inst; +} + +public class DeclarationDefine : ASTDeclaration +{ + ASTIdentifier id; + ASTExpression exp; +} + public class ASTFunctionDefinition : ASTNode { public: @@ -41,7 +55,7 @@ public: void print() { - PrintLn(""); + // PrintLn(""); printIndent(); if(specifiers) { @@ -83,17 +97,23 @@ public: /* union { - FunctionDefinition function; - ClassDefinition _class; - Declaration declaration; - char * importString; - Identifier id; + ASTFunctionDefinition function; + SpecClass _class; + ASTDeclaration declaration; + String importString; + ASTIdentifier id; DBTableDef table; }; - ImportType importType; }; */ +/* +class External +{ + ImportType importType; +} +*/ + public class AST : ASTList { ASTNode ::ParseExternalDeclaration() diff --git a/compiler/libec2/src/lexing.ec b/compiler/libec2/src/lexing.ec index cdaee79..b8c063e 100644 --- a/compiler/libec2/src/lexing.ec +++ b/compiler/libec2/src/lexing.ec @@ -193,7 +193,7 @@ void clearAmbiguity() if(tokenStack.size > stackPos) memmove(tokenStack.array, tokenStack.array + stackPos, (tokenStack.size - stackPos) * sizeof(Token)); tokenStack.size -= stackPos; - stackPos = 0; + stackPos = 0; } } diff --git a/compiler/libec2/src/specifiers.ec b/compiler/libec2/src/specifiers.ec index 36a4b37..1ba0f38 100644 --- a/compiler/libec2/src/specifiers.ec +++ b/compiler/libec2/src/specifiers.ec @@ -4,20 +4,23 @@ import "classes" // Specifiers public class ASTSpecifier : ASTNode { -public: - /* struct - { - //ExtDecl extDecl; - //Symbol symbol; - //OldList * templateArgs; - }; - Expression expression; - NewSpecifier _class; - TemplateParameter templateParameter; - }; - */ }; +public class SpecTypeOf : ASTSpecifier +{ + Expression expression; +} + +public class SpecSubClass : ASTSpecifier +{ + ASTSpecifier _class; +} + +public class SpecTemplateType : ASTSpecifier +{ + TemplateParameter templateParameter; +} + public class SpecsList : ASTList { void printSep() @@ -32,7 +35,7 @@ public class SpecsList : ASTList while(true) { peekToken(); - if(nextToken.type == STRUCT || nextToken.type == UNION) + if(nextToken.type == STRUCT || nextToken.type == UNION || nextToken.type == CLASS || nextToken.type == ENUM) { ASTSpecifier s = SpecClass::parse(); if(s) @@ -83,6 +86,9 @@ public class SpecBase : ASTSpecifier public class SpecName : ASTSpecifier { String name; + //ExtDecl extDecl; + //Symbol symbol; + //List templateArgs; void print() { @@ -90,34 +96,41 @@ public class SpecName : ASTSpecifier } } -public class ASTEnumerator : struct -{ -public: - ASTIdentifier id; - ASTExpression exp; -}; - public class SpecClass : ASTSpecifier { TokenType type; ASTIdentifier id; - List enumerators; SpecsList baseSpecs; ClassDefList definitions; + + //ASTSpecifier _class; + // Symbol symbol; + //Location blockStart; + //Location nameLoc; + //bool deleteWatchable; + //int endid; + //AccessMode declMode; bool addNameSpace; Context ctx; // ExtDecl extDeclStruct; SpecClass ::parse() { - SpecClass spec { }; + SpecClass spec = (peekToken().type == ENUM) ? SpecEnum { } : SpecClass { }; spec.type = readToken().type; if(peekToken().type == IDENTIFIER) spec.id = ASTIdentifier::parse(); + if(peekToken().type == ':') + { + readToken(); + spec.baseSpecs = SpecsList::parse(); + } if(peekToken().type == '{') { readToken(); spec.definitions = ClassDefList::parse(); + if(!spec.definitions) + spec.definitions = { }; if(peekToken().type == '}') readToken(); } @@ -129,44 +142,58 @@ public class SpecClass : ASTSpecifier type.print(); Print(" "); if(id) id.print(); + if(baseSpecs) + { + Print(" : "); + baseSpecs.print(); + } if(definitions) { PrintLn("\n{"); indent++; definitions.print(); indent--; - Print("\n}"); + Print("}"); } } } -/* -public class Attribute : struct +public class ASTEnumerator : ASTNode { public: - Attribute prev, next; - Location loc; + ASTIdentifier id; + ASTExpression exp; +}; + +public class EnumeratorList : ASTList +{ +} + +public class SpecEnum : SpecClass +{ + EnumeratorList enumerators; +} + +public class ASTAttribute : ASTNode +{ String attr; - Expression exp; + ASTExpression exp; } -public class Attrib : struct +public class ASTAttrib : ASTNode { -public: - Location loc; - int type; - OldList * attribs; + TokenType type; + List attribs; +} + +public class ASTExtDecl : ASTNode { } + +public class ExtDeclString : ASTExtDecl +{ + String s; } -public class ExtDecl : struct +public class ExtDeclAttrib : ASTExtDecl { -public: - Location loc; - ExtDeclType type; - union - { - String s; - Attrib attr; - }; + ASTAttrib attr; } -*/ diff --git a/compiler/libec2/src/statements.ec b/compiler/libec2/src/statements.ec index 87c5a0b..f330202 100644 --- a/compiler/libec2/src/statements.ec +++ b/compiler/libec2/src/statements.ec @@ -100,7 +100,7 @@ public: public class StmtExpression : ASTStatement { - ListExp expressions; + ExpList expressions; void print() { @@ -110,7 +110,7 @@ public class StmtExpression : ASTStatement StmtExpression ::parse() { - ListExp exp = ListExp::parse(); + ExpList exp = ExpList::parse(); if(exp) { StmtExpression stmt { expressions = exp }; @@ -233,7 +233,7 @@ public class StmtCompound : ASTStatement public class StmtIf : ASTStatement { - ListExp exp; + ExpList exp; ASTStatement stmt; ASTStatement elseStmt; @@ -259,7 +259,7 @@ public class StmtIf : ASTStatement if(elseStmt._class != class(StmtCompound)) elseStmt.print(); if(elseStmt._class == class(StmtExpression)) PrintLn(""); indent--; - } + } } StmtIf ::parse() @@ -269,7 +269,7 @@ public class StmtIf : ASTStatement if(peekToken().type == '(') { readToken(); - stmt.exp = ListExp::parse(); + stmt.exp = ExpList::parse(); if(peekToken().type == ')') readToken(); stmt.stmt = ASTStatement::parse(); if(peekToken().type == ELSE) @@ -286,7 +286,7 @@ int caseIndent = -1; public class StmtSwitch : ASTStatement { - ListExp exp; + ExpList exp; ASTStatement stmt; void print() @@ -311,7 +311,7 @@ public class StmtSwitch : ASTStatement if(peekToken().type == '(') { readToken(); - stmt.exp = ListExp::parse(); + stmt.exp = ExpList::parse(); if(peekToken().type == ')') readToken(); stmt.stmt = ASTStatement::parse(); } @@ -381,7 +381,7 @@ public class StmtCase : ASTStatement public class StmtWhile : ASTStatement { - ListExp exp; + ExpList exp; ASTStatement stmt; StmtWhile ::parse() @@ -391,7 +391,7 @@ public class StmtWhile : ASTStatement if(peekToken().type == '(') { readToken(); - stmt.exp = ListExp::parse(); + stmt.exp = ExpList::parse(); if(peekToken().type == ')') readToken(); stmt.stmt = ASTStatement::parse(); } @@ -401,7 +401,7 @@ public class StmtWhile : ASTStatement public class StmtDoWhile : ASTStatement { - ListExp exp; + ExpList exp; ASTStatement stmt; StmtDoWhile ::parse() @@ -415,7 +415,7 @@ public class StmtDoWhile : ASTStatement if(peekToken().type == '(') { readToken(); - stmt.exp = ListExp::parse(); + stmt.exp = ExpList::parse(); if(peekToken().type == ')') readToken(); } if(peekToken().type == ';') readToken(); @@ -428,7 +428,7 @@ public class StmtFor : ASTStatement { ASTStatement init; ASTStatement check; - ListExp increment; + ExpList increment; ASTStatement stmt; void print() @@ -467,12 +467,12 @@ public class StmtFor : ASTStatement readToken(); stmt.init = ASTStatement::parse(); stmt.check = ASTStatement::parse(); - stmt.increment = ListExp::parse(); + stmt.increment = ExpList::parse(); if(peekToken().type == ')') { readToken(); stmt.stmt = ASTStatement::parse(); - } + } } return stmt; } @@ -510,7 +510,7 @@ public class StmtContinue : ASTStatement public class StmtReturn : ASTStatement { - ListExp exp; + ExpList exp; void print() { Print("return"); @@ -526,7 +526,7 @@ public class StmtReturn : ASTStatement { StmtReturn stmt { }; readToken(); - if(peekToken().type != ';') stmt.exp = ListExp::parse(); + if(peekToken().type != ';') stmt.exp = ExpList::parse(); if(peekToken().type == ';') readToken(); return stmt; } @@ -583,8 +583,8 @@ public class StmtStopWatching : ASTStatement public class StmtForEach : ASTStatement { Identifier id; - ListExp exp; - ListExp filter; + ExpList exp; + ExpList filter; Statement stmt; } diff --git a/compiler/libec2/test.ec b/compiler/libec2/test.ec index 2eaa696..03cc65e 100644 --- a/compiler/libec2/test.ec +++ b/compiler/libec2/test.ec @@ -1,13 +1,22 @@ +class Form1 : Window +{ + void OnCreate( + + caption = "Form1"; + background = formColor; + borderStyle = sizable; + hasMaximize = true; + hasMinimize = true; + hasClose = true; + clientSize = { 632, 438 }; +} + struct InventoryItem { - float price; + float price = 5; String name; - void Print() - { - int a; - PrintLn(a + 4); - } + price = 10.0f; } item, * itemPtr; class SomeClass @@ -19,6 +28,8 @@ int a; typedef int bla; +// import "ecere" + int SomeFunction(int * p) { int b[3][4] = -- 1.8.3.1