/* Read in the first-stage syntax tree. This will be a Stylesheet node, containing AtRule and TopLevel nodes. */ static node *read_stylesheet(mincss_context *context) { node *sheetnod = new_node(context, nod_Stylesheet); while (1) { tokentype toktyp = context->nexttok.typ; if (toktyp == tok_EOF) break; if (toktyp == tok_CDO || toktyp == tok_CDC) { /* Comment delimiters are ignored at the top level. */ read_token(context); continue; } if (toktyp == tok_Space) { /* We also ignore whitespace between statements. */ read_token(context); continue; } node *nod = read_statement(context); if (nod) node_add_node(sheetnod, nod); } return sheetnod; }
static void do_node_add(bContext *C, bNodeTemplate *ntemp) { Main *bmain = CTX_data_main(C); Scene *scene = CTX_data_scene(C); SpaceNode *snode = CTX_wm_space_node(C); ScrArea *sa = CTX_wm_area(C); ARegion *ar; bNode *node, *node_new; /* get location to add node at mouse */ for (ar = sa->regionbase.first; ar; ar = ar->next) { if (ar->regiontype == RGN_TYPE_WINDOW) { wmWindow *win = CTX_wm_window(C); int x = win->eventstate->x - ar->winrct.xmin; int y = win->eventstate->y - ar->winrct.ymin; if (y < 60) y += 60; UI_view2d_region_to_view(&ar->v2d, x, y, &snode->cursor[0], &snode->cursor[1]); } } /* store selection in temp test flag */ for (node = snode->edittree->nodes.first; node; node = node->next) { if (node->flag & NODE_SELECT) node->flag |= NODE_TEST; else node->flag &= ~NODE_TEST; } node_new = node_add_node(snode, bmain, scene, ntemp, snode->cursor[0], snode->cursor[1]); /* select previous selection before autoconnect */ for (node = snode->edittree->nodes.first; node; node = node->next) { if (node->flag & NODE_TEST) node->flag |= NODE_SELECT; } /* deselect after autoconnection */ for (node = snode->edittree->nodes.first; node; node = node->next) { if (node->flag & NODE_TEST) node->flag &= ~NODE_SELECT; } /* once this is called from an operator, this should be removed */ if (node_new) { char undostr[BKE_UNDO_STR_MAX]; BLI_snprintf(undostr, sizeof(undostr), "Add Node %s", nodeLabel(node_new)); BKE_write_undo(C, undostr); } snode_notify(C, snode); snode_dag_update(C, snode); }
static void do_node_add(bContext *C, bNodeTemplate *ntemp) { Main *bmain= CTX_data_main(C); Scene *scene= CTX_data_scene(C); SpaceNode *snode= CTX_wm_space_node(C); ScrArea *sa= CTX_wm_area(C); ARegion *ar; bNode *node; /* get location to add node at mouse */ for(ar=sa->regionbase.first; ar; ar=ar->next) { if(ar->regiontype == RGN_TYPE_WINDOW) { wmWindow *win= CTX_wm_window(C); int x= win->eventstate->x - ar->winrct.xmin; int y= win->eventstate->y - ar->winrct.ymin; if(y < 60) y+= 60; UI_view2d_region_to_view(&ar->v2d, x, y, &snode->mx, &snode->my); } } /* store selection in temp test flag */ for(node= snode->edittree->nodes.first; node; node= node->next) { if(node->flag & NODE_SELECT) node->flag |= NODE_TEST; else node->flag &= ~NODE_TEST; } /* node= */ node_add_node(snode, bmain, scene, ntemp, snode->mx, snode->my); /* select previous selection before autoconnect */ for(node= snode->edittree->nodes.first; node; node= node->next) { if(node->flag & NODE_TEST) node->flag |= NODE_SELECT; } /* deselect after autoconnection */ for(node= snode->edittree->nodes.first; node; node= node->next) { if(node->flag & NODE_TEST) node->flag &= ~NODE_SELECT; } snode_notify(C, snode); snode_dag_update(C, snode); }
/* Read in a block. When called, the current token must be an LBrace. On return, the current token is whatever was after the RBrace. */ static node *read_block(mincss_context *context) { tokentype toktyp = context->nexttok.typ; if (toktyp == tok_EOF || toktyp != tok_LBrace) { mincss_note_error(context, "(Internal) Unexpected token at read_block"); return NULL; } read_token(context); read_token_skipspace(context); node *nod = new_node(context, nod_Block); while (1) { toktyp = context->nexttok.typ; if (toktyp == tok_EOF) { mincss_note_error(context, "Unexpected end of block"); return nod; } switch (toktyp) { case tok_RBrace: /* Done */ read_token(context); read_token_skipspace(context); return nod; case tok_LBrace: { /* Sub-block */ node *blocknod = read_block(context); if (!blocknod) { /* error, already reported */ continue; } node_add_node(nod, blocknod); continue; } case tok_Semicolon: { node *subnod = new_node_token(context, &context->nexttok); node_add_node(nod, subnod); read_token(context); continue; } case tok_AtKeyword: { node *atnod = new_node_token(context, &context->nexttok); node_add_node(nod, atnod); read_token(context); continue; } case tok_Function: { node *subnod = new_node(context, nod_Function); node_copy_text(subnod, &context->nexttok); node_add_node(nod, subnod); read_token(context); read_any_until_close(context, subnod, tok_RParen); continue; } case tok_LParen: { node *subnod = new_node(context, nod_Parens); node_add_node(nod, subnod); read_token(context); read_any_until_close(context, subnod, tok_RParen); continue; } case tok_LBracket: { node *subnod = new_node(context, nod_Brackets); node_add_node(nod, subnod); read_token(context); read_any_until_close(context, subnod, tok_RBracket); continue; } case tok_CDO: case tok_CDC: mincss_note_error(context, "HTML comment delimiters not allowed inside block"); read_token(context); read_token_skipspace(context); continue; case tok_RParen: mincss_note_error(context, "Unexpected close-paren inside block"); read_token(context); continue; case tok_RBracket: mincss_note_error(context, "Unexpected close-bracket inside block"); read_token(context); continue; default: { /* Anything else is a single "any". */ node *subnod = new_node_token(context, &context->nexttok); node_add_node(nod, subnod); read_token(context); } } } }
/* Read an "any* sequence up until a particular close token (RBracket or RParen). Blocks cannot occur in this context. On return, the current token is whatever's next. */ static void read_any_until_close(mincss_context *context, node *nod, tokentype closetok) { while (1) { tokentype toktyp = context->nexttok.typ; if (toktyp == tok_EOF) { mincss_note_error(context, "Missing close-delimiter"); return; } if (toktyp == closetok) { /* The expected close-token. */ read_token(context); return; } switch (toktyp) { case tok_Semicolon: mincss_note_error(context, "Unexpected semicolon inside brackets"); read_token(context); continue; case tok_LBrace: mincss_note_error(context, "Unexpected block inside brackets"); read_block(context); continue; case tok_Function: { node *subnod = new_node(context, nod_Function); node_copy_text(subnod, &context->nexttok); node_add_node(nod, subnod); read_token(context); read_any_until_close(context, subnod, tok_RParen); continue; } case tok_LParen: { node *subnod = new_node(context, nod_Parens); node_add_node(nod, subnod); read_token(context); read_any_until_close(context, subnod, tok_RParen); continue; } case tok_LBracket: { node *subnod = new_node(context, nod_Brackets); node_add_node(nod, subnod); read_token(context); read_any_until_close(context, subnod, tok_RBracket); continue; } case tok_CDO: case tok_CDC: mincss_note_error(context, "HTML comment delimiters not allowed inside brackets"); read_token(context); read_token_skipspace(context); continue; case tok_RParen: mincss_note_error(context, "Unexpected close-paren inside brackets"); read_token(context); continue; case tok_RBracket: mincss_note_error(context, "Unexpected close-bracket inside brackets"); read_token(context); continue; case tok_AtKeyword: mincss_note_error(context, "Unexpected @-keyword inside brackets"); read_token(context); continue; default: { node *toknod = new_node_token(context, &context->nexttok); node_add_node(nod, toknod); read_token(context); } } } }
/* Read an "any*" sequence, up until end-of-file or an AtKeyword token. Appends nodes to the node passed in (which will be a TopLevel). On return, the current token is EOF, LBrace (meaning start of a block), or AtKeyword. */ static void read_any_top_level(mincss_context *context, node *nod) { while (1) { tokentype toktyp = context->nexttok.typ; if (toktyp == tok_EOF) { return; /* end of file */ } switch (toktyp) { case tok_LBrace: return; case tok_Function: { node *subnod = new_node(context, nod_Function); node_copy_text(subnod, &context->nexttok); node_add_node(nod, subnod); read_token(context); read_any_until_close(context, subnod, tok_RParen); continue; } case tok_LParen: { node *subnod = new_node(context, nod_Parens); node_add_node(nod, subnod); read_token(context); read_any_until_close(context, subnod, tok_RParen); continue; } case tok_LBracket: { node *subnod = new_node(context, nod_Brackets); node_add_node(nod, subnod); read_token(context); read_any_until_close(context, subnod, tok_RBracket); continue; } case tok_CDO: case tok_CDC: /* Swallow, ignore */ read_token(context); read_token_skipspace(context); continue; case tok_RParen: mincss_note_error(context, "Unexpected close-paren"); read_token(context); continue; case tok_RBracket: mincss_note_error(context, "Unexpected close-bracket"); read_token(context); continue; case tok_AtKeyword: return; case tok_Semicolon: { node *toknod = new_node_token(context, &context->nexttok); node_add_node(nod, toknod); read_token(context); read_token_skipspace(context); continue; } default: { node *toknod = new_node_token(context, &context->nexttok); node_add_node(nod, toknod); read_token(context); } } } }
/* Read one AtRule or TopLevel. A TopLevel is basically a sequence of anything that isn't an AtRule. */ static node *read_statement(mincss_context *context) { tokentype toktyp = context->nexttok.typ; if (toktyp == tok_EOF) return NULL; if (toktyp == tok_AtKeyword) { node *nod = new_node(context, nod_AtRule); node_copy_text(nod, &context->nexttok); read_token(context); read_token_skipspace(context); read_any_until_semiblock(context, nod); toktyp = context->nexttok.typ; if (toktyp == tok_EOF) { return nod; /* end of file */ } if (toktyp == tok_Semicolon) { /* drop the semicolon, end the AtRule */ read_token(context); read_token_skipspace(context); return nod; } if (toktyp == tok_LBrace) { /* beginning of block */ node *blocknod = read_block(context); if (!blocknod) { /* error */ free_node(nod); return NULL; } node_add_node(nod, blocknod); return nod; /* the block ends the AtRule */ } /* error */ mincss_note_error(context, "(Internal) Unexpected token after read_any_until_semiblock"); free_node(nod); return NULL; } else { /* The syntax spec lets us parse a ruleset here. But we don't bother; we just parse any/blocks until the next AtKeyword. They all get stuffed into a single TopLevel node. (Unless there's no content at all, in which case we don't create a node.) */ node *nod = new_node(context, nod_TopLevel); while (1) { read_any_top_level(context, nod); tokentype toktyp = context->nexttok.typ; if (toktyp == tok_EOF) { break; /* end of file */ } if (toktyp == tok_AtKeyword) { break; /* an @-rule is next */ } if (toktyp == tok_LBrace) { node *blocknod = read_block(context); if (!blocknod) { /* error, already reported */ continue; } node_add_node(nod, blocknod); continue; } mincss_note_error(context, "(Internal) Unexpected token after read_any_top_level"); free_node(nod); return NULL; } if (nod->numnodes == 0) { /* empty group, don't bother returning it. */ free_node(nod); return NULL; } return nod; } }