public static void parse(Token routineName, bool hidden, bool final, bool isOverride, int pure_safe, iSCOPE context) { ROUTINE routine = null; if (routineName.code == TokenCode.Init) { Debug.Indent(); Debug.WriteLine("Entering INITIALIZER.parse"); routine = new INITIALIZER(); goto Init; } Debug.Indent(); Debug.WriteLine("Entering ROUTINE.parse (" + routineName.image + ")"); string image = routineName.image; Token token = get(); // What's after the routine name? switch (routineName.image) { case "and": if (token.code == TokenCode.Then) { forget(); image += " then"; Span span = new Span(routineName.span, token.span); routineName = new Token(span, TokenCode.Identifier, image, new Category(CategoryCode.identifier)); } break; case "or": token = get(); if (token.code == TokenCode.Else) { forget(); image += " else"; Span span = new Span(routineName.span, token.span); routineName = new Token(span, TokenCode.Identifier, image, new Category(CategoryCode.identifier)); } break; } routine = new ROUTINE(pure_safe, isOverride, routineName); Init: routine.setSpecs(hidden, final); Context.enter(routine); if (routineName.code == TokenCode.Init) { goto Init2; } token = get(); if (token.code == TokenCode.Alias) { forget(); token = expect(TokenCode.Identifier); routine.alias = new IDENTIFIER(token.image); } if (token.code == TokenCode.LBracket) { // Generic routine forget(); while (true) { var generic = FORMAL_GENERIC.parse(context); routine.add(generic); token = get(); switch (token.code) { case TokenCode.Comma: case TokenCode.Semicolon: forget(); continue; case TokenCode.RBracket: forget(); goto Finish; default: { /* Syntax error */ break; } } } Finish: ; } Init2: token = get(); if (token.code == TokenCode.LParen) { forget(); token = get(); if (token.code == TokenCode.RParen) { // Empty parameter list forget(); goto Weiter; } while (true) { VARIABLE.parse(false, false, false, false, null, null, routine); token = get(); if (token.code == TokenCode.Comma) { forget(); continue; } if (token.code == TokenCode.Semicolon) { forget(); continue; } break; } expect(TokenCode.RParen); } Weiter: token = get(); if (token.code == TokenCode.Colon) { forget(); bool ref_val, conc; // TEMP SOLUTION Span span2; routine.type = VARIABLE.parseTypeSpecifier(routine, out ref_val, out conc, out span2); if (routine.type != null) { routine.type.parent = routine; routine.type.setSpan(span2); } } token = get(); if (token.code == TokenCode.Require) { forget(); token = get(); if (token.code == TokenCode.Else) { forget(); routine.requireElse = true; } while (true) { EXPRESSION precondition = EXPRESSION.parse(null, routine); routine.addPre(precondition); precondition.parent = routine; token = get(); if (token.code == TokenCode.Is || token.code == TokenCode.Arrow) { break; } } } if (token.code == TokenCode.Arrow) { forget(); BODY body = new BODY(); routine.routineBody = body; body.parent = routine; Context.enter(body); EXPRESSION expression = EXPRESSION.parse(null, body); RETURN ret = new RETURN(expression); expression.parent = ret; ret.setSpan(expression.span); ret.parent = body; body.add(ret); body.setSpan(ret.span); Context.exit(); } else if (token.code == TokenCode.Is) { forget(); token = get(); if (token.code == TokenCode.Abstract) { forget(); routine.isAbstract = true; } else if (token.code == TokenCode.Foreign) { forget(); routine.isForeign = true; } else { BODY body = new BODY(); body.parent = routine; routine.routineBody = body; Context.enter(body); BODY.parse(TokenCode.End, TokenCode.Ensure, TokenCode.ERROR, body); Context.exit(); } token = get(); if (token.code == TokenCode.Ensure) { forget(); token = get(); if (token.code == TokenCode.Then) { forget(); routine.ensureThen = true; } ENTITY.weAreWithinEnsure = true; while (true) { EXPRESSION postcondition = EXPRESSION.parse(null, routine); routine.addPre(postcondition); postcondition.parent = routine; token = get(); if (token.code == TokenCode.End) { forget(); break; } } ENTITY.weAreWithinEnsure = false; } else if (!routine.isAbstract && !routine.isForeign) { expect(TokenCode.End); } } token = get(); if (token.code == TokenCode.Semicolon) { forget(); } Context.exit(); context.add(routine); routine.parent = context.self; routine.setSpan(routineName, token); if (routineName.code == TokenCode.Init) { Debug.WriteLine("Exiting INITIALIZER.parse"); } else { Debug.WriteLine("Exiting ROUTINE.parse"); } Debug.Unindent(); }
/// <summary> /// /// </summary> /// <syntax> /// Объявление-контейнера /// : [ Спецификатор-контейнера ] unit Имя-контейнера [ FormalGenerics ] /// { Директива-контейнера } /// is /// Тело-контейнера /// [ invariant Список-предикатов ] /// end /// /// Спецификатор-контейнера /// : ref | val | concurrent | abstract /// /// Имя-контейнера /// : Составное-имя /// /// Директива-контейнера /// : Директива-наследования /// | Директива-использования /// /// Директива-наследования /// : extend Базовый-контейнер { , Базовый-контейнер } /// /// Базовый-контейнер /// : [ ~ ] UnitTypeName /// /// Тело-контейнера /// : { Объявление } /// </syntax> /// <returns></returns> public static void parse(bool hidden, bool final, bool abstr, iSCOPE context) { Debug.Indent(); Debug.WriteLine("Entering UNIT.parse"); bool ref_val = false; // unit is reference by default bool concurrent = false; UNIT unit = null; Token token = get(); Token begin = token; TokenCode code = TokenCode.Unit; switch (token.code) { case TokenCode.Ref: ref_val = true; forget(); code = getUnitKeyword(); break; case TokenCode.Val: ref_val = false; forget(); code = getUnitKeyword(); break; case TokenCode.Abstract: abstr = true; forget(); code = getUnitKeyword(); break; case TokenCode.Concurrent: concurrent = true; forget(); code = getUnitKeyword(); break; case TokenCode.Unit: code = TokenCode.Unit; forget(); break; case TokenCode.Package: code = TokenCode.Package; forget(); break; } // 1. Unit header token = expect(TokenCode.Identifier); Token compoundName = IDENTIFIER.parseCompoundName(token); if (code == TokenCode.Package) { if (!ENTITY.options.optConfig) { warning(token, "no-config"); unit = new UNIT(compoundName.image, ref_val, abstr, concurrent); } else { unit = new PACKAGE(compoundName.image, ref_val, abstr, concurrent); } } else { unit = new UNIT(compoundName.image, ref_val, abstr, concurrent); } Debug.WriteLine("======================" + compoundName.image); unit.parent = context.self; unit.setSpecs(hidden, final); Context.enter(unit); // 2. Generic parameters token = get(); if (token.code == TokenCode.LBracket) { forget(); while (true) { var generic = FORMAL_GENERIC.parse(unit); unit.add(generic); token = get(); switch (token.code) { case TokenCode.Comma: case TokenCode.Semicolon: forget(); continue; case TokenCode.RBracket: forget(); goto Finish; default: { /* Syntax error */ break; } } } Finish: ; } // Possible unit alias token = get(); if (token.code == TokenCode.Alias) { forget(); token = expect(TokenCode.Identifier); unit.alias = new IDENTIFIER(token); } // 3. Unit directives: inheritance token = get(); if (token.code == TokenCode.Extend) { forget(); while (true) { PARENT parent = PARENT.parse(unit); if (parent == null) /* Syntax error */ break { ; } unit.add(parent); token = get(); switch (token.code) { case TokenCode.Comma: case TokenCode.Semicolon: case TokenCode.EOL: forget(); continue; default: goto Use; } } }