MCPcopy Create free account
hub / github.com/Redot-Engine/redot-engine / parse_program

Method parse_program

modules/gdscript/gdscript_parser.cpp:610–781  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

608}
609
610void GDScriptParser::parse_program() {
611 head = alloc_node<ClassNode>();
612 head->start_line = 1;
613 head->end_line = 1;
614 head->fqcn = GDScript::canonicalize_path(script_path);
615 current_class = head;
616 bool can_have_class_or_extends = true;
617
618#define PUSH_PENDING_ANNOTATIONS_TO_HEAD \
619 if (!annotation_stack.is_empty()) { \
620 for (AnnotationNode *annot : annotation_stack) { \
621 head->annotations.push_back(annot); \
622 } \
623 annotation_stack.clear(); \
624 }
625
626 while (!check(GDScriptTokenizer::Token::TK_EOF)) {
627 if (match(GDScriptTokenizer::Token::ANNOTATION)) {
628 AnnotationNode *annotation = parse_annotation(AnnotationInfo::SCRIPT | AnnotationInfo::CLASS_LEVEL | AnnotationInfo::STANDALONE);
629 if (annotation != nullptr) {
630 if (annotation->applies_to(AnnotationInfo::CLASS)) {
631 // We do not know in advance what the annotation will be applied to: the `head` class or the subsequent inner class.
632 // If we encounter `class_name`, `extends` or pure `SCRIPT` annotation, then it's `head`, otherwise it's an inner class.
633 annotation_stack.push_back(annotation);
634 } else if (annotation->applies_to(AnnotationInfo::SCRIPT)) {
635 PUSH_PENDING_ANNOTATIONS_TO_HEAD;
636 if (annotation->name == SNAME("@tool") || annotation->name == SNAME("@icon") || annotation->name == SNAME("@static_unload")) {
637 // Some annotations need to be resolved and applied in the parser.
638 // The root class is not in any class, so `head->outer == nullptr`.
639 annotation->apply(this, head, nullptr);
640 } else {
641 head->annotations.push_back(annotation);
642 }
643 } else if (annotation->applies_to(AnnotationInfo::STANDALONE)) {
644 if (previous.type != GDScriptTokenizer::Token::NEWLINE) {
645 push_error(R"(Expected newline after a standalone annotation.)");
646 }
647 if (annotation->name == SNAME("@export_category") || annotation->name == SNAME("@export_group") || annotation->name == SNAME("@export_subgroup")) {
648 head->add_member_group(annotation);
649 // This annotation must appear after script-level annotations and `class_name`/`extends`,
650 // so we stop looking for script-level stuff.
651 can_have_class_or_extends = false;
652 break;
653 } else if (annotation->name == SNAME("@warning_ignore_start") || annotation->name == SNAME("@warning_ignore_restore")) {
654 // Some annotations need to be resolved and applied in the parser.
655 annotation->apply(this, nullptr, nullptr);
656 } else {
657 push_error(R"(Unexpected standalone annotation.)");
658 }
659 } else {
660 annotation_stack.push_back(annotation);
661 // This annotation must appear after script-level annotations and `class_name`/`extends`,
662 // so we stop looking for script-level stuff.
663 can_have_class_or_extends = false;
664 break;
665 }
666 }
667 } else if (check(GDScriptTokenizer::Token::LITERAL) && current.literal.get_type() == Variant::STRING) {

Callers

nothing calls this directly

Calls 10

MINFunction · 0.85
applies_toMethod · 0.80
add_member_groupMethod · 0.80
begins_withMethod · 0.80
push_backMethod · 0.45
applyMethod · 0.45
get_typeMethod · 0.45
is_emptyMethod · 0.45
get_lineMethod · 0.45
hasMethod · 0.45

Tested by

no test coverage detected