Beispiel #1
0
 sptr<Node> Parser::ParseSwitchCase()
 {
     sptr<StmntNode> root(new StmntNode(currToken));
     NextToken();
     root->PushChild(ParseExp());
     Expect(OF, -1);
     sptr<Node> caseList(new ListNode(ParseConstList(), "Case list"));
     Expect(COLON, -1);
     caseList->PushChild(ParseStatement());
     while (MatchSkip(SEMICOLON, -1))
     {
         caseList->PushChild(ParseConstList());
         Expect(COLON, -1);
         caseList->PushChild(ParseStatement());
     }
     root->PushChild(caseList);
     Expect(END, -1);
     return root;
 }
Beispiel #2
0
/*
Type * ParseIntRange(Type * type)
{
	Var * min, * max;
	Bookmark bookmark;

	bookmark = SetBookmark();
	ParseExpressionType(TypeType(NULL));
	if (TOK && TOP != 0) {
		min = BufPop();
		max = NULL;
		if (NextIs(TOKEN_DOTDOT)) {
			ExpectExpression(NULL);
			if (TOK) {
				max = BufPop();
				type = TypeDerive(type);
			}
		}

		if (VarIsIntConst(min) && VarIsIntConst(max)) {
			type = TypeAllocRange(min, max);

			if (type->range.min > type->range.max) {
				SyntaxErrorBmk("range minimum bigger than maximum", bookmark);
			}

		} else {
			SyntaxErrorBmk("expected type constant expression", bookmark);
		}
	}
	return type;
}
*/
Type * ParseType2(InstrOp mode)
/*
Purpose:
	Parse: <int> [".." <int>] | <var> | proc <VarList>
Input:
	mode	Type of variable for which we parse.
*/
{
	
	Var * var;
	Type * type = NULL, * variant_type = NULL;
	Var * min, * max;
	Bookmark bookmark;

next:
	type = ParseType3();
	if (!TOK) return NULL;

	if (type == NULL) {
		bookmark = SetBookmark();
		ParseExpressionType(TypeType(NULL));
		if (TOK && TOP != 0) {
			min = BufPop();
			max = NULL;
			if (NextIs(TOKEN_DOTDOT)) {
				ExpectExpression(NULL);
				if (TOK) {
					max = BufPop();
				}
			}

			type = NULL;
			if (max == NULL) {
				var = min;
				if (var->mode == INSTR_TYPE) {
					type = var->type;
				} else if (var->mode == INSTR_VAR && var->type->variant == TYPE_TYPE) {
					type = var->type_value;
					SetFlagOn(var->submode, SUBMODE_USED_AS_TYPE);
				}

				// This is directly type
				if (type != NULL) {
					// For integer type, constants may be defined
					if (type->variant == TYPE_INT) {
//						type = ParseIntRange(type);
						goto const_list;
					}
					goto done;
				}
				max = var;		
			}

			if (VarIsIntConst(min) && VarIsIntConst(max)) {
				type = TypeAllocRange(min, max);

				if (type->range.min > type->range.max) {
					SyntaxErrorBmk("range minimum bigger than maximum", bookmark);
				}

			} else {
				SyntaxErrorBmk("expected type constant expression", bookmark);
			}
		} else if (TOK == TOKEN_STRING) {
			type = TypeAlloc(TYPE_VAR);
			type->typevar = VarNewStr(NAME);
			NextToken();
		}
	}

const_list:
	// Parse type specific constants
	// There can be list of constants specified in block.
	// First thing in the block must be an identifier, so we try to open the block with this in mind.
	// We try to parse constants only for integer types (in future, we may try other numberic or string types)

	if (type != NULL && type->variant == TYPE_INT && !type->is_enum) {
		if (TOK != TOKEN_OR) {
			type = ParseConstList(type);
		}
	}
done:
	if (TOK) {
		if (variant_type != NULL) {
			variant_type->right = type;
			type = variant_type;
		}

		if (NextIs(TOKEN_OR)) {
			variant_type = TypeAlloc(TYPE_VARIANT);
			variant_type->left = type;
			goto next;
		}
	}
	return type;
}
Beispiel #3
0
Type * ParseType3()
{
	Type * type = NULL, * variant_type = NULL;
	Type * elmt, * t;
	Var * var;
	BigInt * st;

	//# "type" restrict_type
	if (NextIs(TOKEN_TYPE2)) {
		variant_type = ParseType2(INSTR_VAR);
		type = TypeType(variant_type);
	//# "enum" ["struct"]
	} else if (NextIs(TOKEN_ENUM)) {
		type = TypeAlloc(TYPE_INT);
		type->range.flexible = true;
		type->is_enum        = true;
		if (NextIs(TOKEN_STRUCT)) {
			ParseEnumStruct(type);
		} else {
			type = ParseConstList(type);
		}

	//# "proc" args
	} else if (NextIs(TOKEN_PROC)) {
		type = TypeAlloc(TYPE_PROC);
		ParseArgList(SUBMODE_ARG_IN, type);
		if (TOK) {
			ProcTypeFinalize(type);
		}
	//# "macro" args
	} else if (NextIs(TOKEN_MACRO)) {

		type = TypeAlloc(TYPE_MACRO);
		ParseArgList(SUBMODE_ARG_IN, type);

	// Struct
	} else if (NextIs(TOKEN_STRUCT)) {
		type = TypeAlloc(TYPE_STRUCT);
		ParseArgList(SUBMODE_EMPTY, type);

	// String
	} else if (NextIs(TOKEN_STRING_TYPE)) {
		type = TypeAlloc(TYPE_STRING);

	// Array
	} else if (NextIs(TOKEN_ARRAY)) {		
		type = TypeAlloc(TYPE_ARRAY);
		t = NULL;

		if (TOK == TOKEN_OPEN_P) {
			EnterBlockWithStop(TOKEN_EQUAL);
			while (TOK != TOKEN_ERROR && !NextIs(TOKEN_BLOCK_END)) {
				elmt = ParseIntType();
				if (type->index == NULL) {
					type->index = elmt;
				} else if (t != NULL) {
					t->right = TypeTuple(t->right, elmt);
					t = t->right;
				} else {
					t = TypeTuple(type->index, elmt);
					type->index = t;
				}
				NextIs(TOKEN_COMMA);
			};
		}
		
		// If no dimension has been defined, use flexible array.
		// This is possible only for constants now.

		if (TOK) {
			if (type->index == NULL) {
				elmt = TypeAlloc(TYPE_INT);
				elmt->range.flexible = true;
				elmt->range.min = 0;
				type->index = elmt;
			}
		}

		// Element STEP may be defined
		if (TOK) {
			if (NextIs(TOKEN_STEP)) {
				ExpectExpression(NULL);
				if (TOK) {
					var = STACK[0];
					st = VarIntConst(var);
					if (st != NULL) {
						type->step = IntN(st);
					} else {
						SyntaxError("Expected integer constant");
					}
				}
			}
		}

		if (TOK) {
			if (NextIs(TOKEN_OF)) {
				type->element = ParseSubtype();
			} else {
				type->element = TypeByte();
			}
		}

		if (TOK) {
			if (type->step == 0) {
				type->step = TypeSize(type->element);
			}
		}

	} else if (NextIs(TOKEN_ADR2)) {
		elmt = NULL;
		if (NextIs(TOKEN_OF)) {
			elmt = ParseSubtype();
		}
		type = TypeAdrOf(elmt);
	}
	return type;
}