public UNIT_REF(UNIT u) : this() { name = u.name.identifier; unit_ref = u; }
/// <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; } } }
/// <summary> /// /// </summary> /// <returns></returns> public static new EXPRESSION parse(Token first, iSCOPE context) { EXPRESSION result = null; Token token = (first == null) ? get() : first; Token begin = token; switch (token.code) { case TokenCode.This: forget(); UNIT unit = Context.unit(); if (unit == null) { // Error message! result = new THIS(null); } else { result = new THIS(unit); result.setSpan(token); } break; case TokenCode.Return: if (!ENTITY.weAreWithinEnsure) { break; } forget(); ROUTINE routine = Context.routine(); if (routine == null) { } // error else { result = new RETURN_EXPR(routine); result.setSpan(token); } break; case TokenCode.Old: forget(); result = EXPRESSION.parse(null, context); Span end = result.span; OLD old = new OLD(result); result.parent = old; result = old; result.setSpan(begin.span, end); break; case TokenCode.If: result = CONDITIONAL.parse(context); break; case TokenCode.LParen: forget(); Span start_tuple = token.span; result = EXPRESSION.parse(null, context); token = get(); if (token.code == TokenCode.Comma) { // Seems to be a tuple forget(); TUPLE_EXPR tuple = new TUPLE_EXPR(); tuple.add(result); while (true) { EXPRESSION expr = EXPRESSION.parse(null, context); tuple.add(expr); token = get(); if (token.code != TokenCode.Comma) { break; } forget(); } result = tuple; } end = expect(TokenCode.RParen).span; result.setSpan(token.span, end); break; case TokenCode.Identifier: if (first == null) { forget(); ////// perhaps the same condition should be added for all cases? } DECLARATION d = Context.find(token); if (d == null) { result = new UNRESOLVED(context, new IDENTIFIER(token)); } else { result = new REFERENCE(d); } Token token2 = get(); if (token2.code == TokenCode.LBracket) { UNIT_REF unitRef = UNIT_REF.parse(token, false, context); result = new NEW(unitRef); result.setSpan(unitRef.span); } else { result.setSpan(token); } break; case TokenCode.Integer: case TokenCode.Real: case TokenCode.String: case TokenCode.Character: result = new LITERAL(token.value, token.span, token.code); result.setSpan(token); forget(); break; default: return(null); } // result.setSpan(token); return(result); }
public THIS(UNIT u) : base() { unit = u; type = new UNIT_REF(u); }
public static void parse(TokenCode stop1, TokenCode stop2, TokenCode stop3, iSCOPE context) { Debug.Indent(); Debug.WriteLine("Entering BODY.parse"); Token token; Token start = get(); while (true) { bool res = STATEMENT.parse(context, stop1, stop2, stop3); if (!res) { // Neither a statement nor a simple declaration. // Perhaps, a nested/local function? token = get(); switch (token.code) { case TokenCode.Routine: case TokenCode.Safe: case TokenCode.Pure: forget(); int pure_safe = 0; switch (token.code) { case TokenCode.Pure: pure_safe = 1; break; case TokenCode.Safe: pure_safe = 2; break; } ROUTINE.parse(null, false, false, false, pure_safe, context); break; case TokenCode.Unit: case TokenCode.Ref: case TokenCode.Val: // A _local_ unit??? UNIT.parse(context); break; default: // What's this? break; } } token = get(); if (token.code == TokenCode.Semicolon /*|| wasEOL*/) { forget(); } if (token.code == stop1) { break; // don't 'forget()' } if (stop2 != TokenCode.ERROR && token.code == stop2) { break; // don't 'forget()' } if (stop3 != TokenCode.ERROR && token.code == stop3) { break; // don't 'forget()' } } BODY body = context as BODY; if (body == null) /* A system error */ } {
public static bool parse(iSCOPE context) { Debug.Indent(); Debug.WriteLine("Entering DECLARATION.parse"); bool result = true; bool isHidden = false; bool isFinal = false; int pure_safe = 0; bool isOverride = false; bool isRoutine = false; bool isAbstract = false; Token token = get(); Token begin = token; // Collecting specifiers while (true) { switch (token.code) { case TokenCode.Abstract: isAbstract = true; forget(); break; case TokenCode.Override: isOverride = true; forget(); break; case TokenCode.Hidden: isHidden = true; forget(); break; case TokenCode.Final: isFinal = true; isRoutine = true; forget(); break; case TokenCode.Routine: isRoutine = true; forget(); break; case TokenCode.Pure: pure_safe = 1; isRoutine = true; forget(); break; case TokenCode.Safe: pure_safe = 2; isRoutine = true; forget(); break; default: goto OutLoop; } token = get(); } OutLoop: // Checking for a leading keyword switch (token.code) { case TokenCode.Unit: if (isOverride || isRoutine || pure_safe > 0) { // Illegal specifier for unit declaration error(token, "illegal-spec", begin, "unit declaration"); } UNIT.parse(isHidden, isFinal, isAbstract, context); break; case TokenCode.Const: if (isRoutine || pure_safe > 0) { // Illegal specifier for constant declaration error(begin, "illegal-spec", begin, "object declaration"); } Token start = token; forget(); token = get(); if (token.code == TokenCode.Is) { forget(); if (isOverride) { // Illegal specifier for constant declaration error(begin, "illegal-spec", begin, "constant declaration"); } CONSTANT.parse(isHidden, isFinal, start, context); } else { if (pure_safe > 0) { // Illegal specifier for variable declaration error(begin, "illegal-spec", begin, "variable declaration"); } VARIABLE.parse(isHidden, isFinal, true, isOverride, null, null, context); } break; case TokenCode.Init: forget(); if (isOverride || isFinal || isRoutine || pure_safe > 0) { // Illegal specifier for initializer error(begin, "illegal-spec", begin, "initializer declaration"); } ROUTINE.parse(token, isHidden, isFinal, false, 0, context); break; case TokenCode.Identifier: // An identifier just following (optional) specifier(s) if (isRoutine || pure_safe > 0) { // This is definitely a routine declaration // (Some time after, 'isRoutine' might be removed...) forget(); ROUTINE.parse(token, isHidden, isFinal, isOverride, pure_safe, context); } else { // Decide whether this is variable or routine declaration if (!isOverride || !isHidden || !isFinal) { if (!(context is UNIT)) { // Tricky point: // We are out of a unit context, i.e., within a routine // or in a global scope, AND there is NO ONE specifier given. // So, we conclude that identifier starts a statement // but not a declaration. // We do nothing and silently exit with result == false. break; } } Token id = token; forget(); token = get(); // forget(); switch (token.code) { case TokenCode.LParen: case TokenCode.LBracket: case TokenCode.Then: case TokenCode.Else: ROUTINE.parse(id, isHidden, isFinal, isOverride, pure_safe, context); break; default: forget(); VARIABLE.parse(isHidden, isFinal, false, isOverride, id, token, context); break; } break; } break; default: // Some other token after optional specifier(s). // Perhaps this is an operator sign? Token name = ROUTINE.detectOperatorSign(token); if (name.code != TokenCode.ERROR) { ROUTINE.parse(name, isHidden, isFinal, isOverride, pure_safe, context); } else if (isRoutine || isOverride || isHidden) { // Syntax error in declaration error(token, "syntax-error", "wrong declaration"); result = false; } else { // What's this? -- something that is not a declaration. // Don't issue a message // error(token,"syntax-error"); result = false; } break; } Debug.WriteLine("Exiting DECLARATION.parse"); Debug.Unindent(); return(result); }
/// <summary> /// /// </summary> /// <returns></returns> public static COMPILATION parse() { Debug.Indent(); Debug.WriteLine("Entering COMPILATION.parse"); COMPILATION compilation = new COMPILATION(); Context.enter(compilation); Token start = get(); Token startAnon = null; Token endAnon = null; int pure_safe = 0; while (true) { Token token = get(); Token begin = token; switch (token.code) { case TokenCode.Final: forget(); token = get(); switch (token.code) { case TokenCode.Unit: case TokenCode.Package: case TokenCode.Ref: case TokenCode.Val: case TokenCode.Concurrent: // Don't forget() UNIT.parse(false, true, false, compilation); break; case TokenCode.Abstract: forget(); UNIT.parse(false, true, true, compilation); break; case TokenCode.Safe: case TokenCode.Pure: case TokenCode.Routine: forget(); switch (token.code) { case TokenCode.Pure: pure_safe = 1; break; case TokenCode.Safe: pure_safe = 2; break; } ROUTINE.parse(null, false, true, false, pure_safe, compilation); pure_safe = 0; break; } break; case TokenCode.Ref: case TokenCode.Val: case TokenCode.Concurrent: case TokenCode.Unit: case TokenCode.Package: UNIT.parse(false, false, false, compilation); break; case TokenCode.Abstract: forget(); UNIT.parse(false, false, true, compilation); break; case TokenCode.Use: USE.parse(compilation); break; case TokenCode.Routine: case TokenCode.Safe: case TokenCode.Pure: forget(); switch (token.code) { case TokenCode.Pure: pure_safe = 1; break; case TokenCode.Safe: pure_safe = 2; break; } ROUTINE.parse(null, false, false, false, pure_safe, compilation); pure_safe = 0; break; case TokenCode.EOS: goto Finish; case TokenCode.EOL: forget(); break; default: // A call/assignment statement, or an error if (startAnon == null) { startAnon = get(); } bool result = STATEMENT.parse(compilation.anonymous.routineBody, TokenCode.EOS, TokenCode.ERROR, TokenCode.ERROR); if (!result) { // There was not a statement: // apparently, this is a syntax error goto Finish; } endAnon = get(); break; } } Finish: compilation.setSpan(start, get()); if (startAnon != null && endAnon != null) { compilation.anonymous.setSpan(startAnon, endAnon); } Debug.WriteLine("Exiting COMPILATION.parse"); Debug.Unindent(); Context.exit(); return(compilation); }