version 1.71, 2017/06/26 20:09:04 |
version 1.75, 2017/07/07 17:16:17 |
Line 286 enum parse_mode { |
|
Line 286 enum parse_mode { |
|
static struct eqn_box *eqn_box_alloc(struct eqn_node *, struct eqn_box *); |
static struct eqn_box *eqn_box_alloc(struct eqn_node *, struct eqn_box *); |
static void eqn_box_free(struct eqn_box *); |
static void eqn_box_free(struct eqn_box *); |
static struct eqn_box *eqn_box_makebinary(struct eqn_node *, |
static struct eqn_box *eqn_box_makebinary(struct eqn_node *, |
enum eqn_post, struct eqn_box *); |
struct eqn_box *); |
static void eqn_def(struct eqn_node *); |
static void eqn_def(struct eqn_node *); |
static struct eqn_def *eqn_def_find(struct eqn_node *); |
static struct eqn_def *eqn_def_find(struct eqn_node *); |
static void eqn_delim(struct eqn_node *); |
static void eqn_delim(struct eqn_node *); |
Line 541 eqn_box_alloc(struct eqn_node *ep, struct eqn_box *par |
|
Line 541 eqn_box_alloc(struct eqn_node *ep, struct eqn_box *par |
|
* The new EQN_SUBEXPR will have a two-child limit. |
* The new EQN_SUBEXPR will have a two-child limit. |
*/ |
*/ |
static struct eqn_box * |
static struct eqn_box * |
eqn_box_makebinary(struct eqn_node *ep, |
eqn_box_makebinary(struct eqn_node *ep, struct eqn_box *parent) |
enum eqn_post pos, struct eqn_box *parent) |
|
{ |
{ |
struct eqn_box *b, *newb; |
struct eqn_box *b, *newb; |
|
|
Line 554 eqn_box_makebinary(struct eqn_node *ep, |
|
Line 553 eqn_box_makebinary(struct eqn_node *ep, |
|
parent->last = b->prev; |
parent->last = b->prev; |
b->prev = NULL; |
b->prev = NULL; |
newb = eqn_box_alloc(ep, parent); |
newb = eqn_box_alloc(ep, parent); |
newb->pos = pos; |
|
newb->type = EQN_SUBEXPR; |
newb->type = EQN_SUBEXPR; |
newb->expectargs = 2; |
newb->expectargs = 2; |
newb->args = 1; |
newb->args = 1; |
Line 669 eqn_parse(struct eqn_node *ep, struct eqn_box *parent) |
|
Line 667 eqn_parse(struct eqn_node *ep, struct eqn_box *parent) |
|
const char *cp, *cpn; |
const char *cp, *cpn; |
char *p; |
char *p; |
enum eqn_tok tok; |
enum eqn_tok tok; |
enum eqn_post pos; |
|
enum { CCL_LET, CCL_DIG, CCL_PUN } ccl, ccln; |
enum { CCL_LET, CCL_DIG, CCL_PUN } ccl, ccln; |
int size; |
int size; |
|
|
Line 683 eqn_parse(struct eqn_node *ep, struct eqn_box *parent) |
|
Line 680 eqn_parse(struct eqn_node *ep, struct eqn_box *parent) |
|
if (ep->data == NULL) |
if (ep->data == NULL) |
return ROFF_IGN; |
return ROFF_IGN; |
|
|
ep->start = ep->end = ep->data; |
ep->start = ep->end = ep->data + strspn(ep->data, " ^~"); |
|
|
next_tok: |
next_tok: |
tok = eqn_next(ep, MODE_TOK); |
tok = eqn_next(ep, MODE_TOK); |
|
|
cur->type = EQN_TEXT; |
cur->type = EQN_TEXT; |
cur->text = mandoc_strdup(""); |
cur->text = mandoc_strdup(""); |
} |
} |
parent = eqn_box_makebinary(ep, EQNPOS_NONE, parent); |
parent = eqn_box_makebinary(ep, parent); |
parent->type = EQN_LISTONE; |
parent->type = EQN_LIST; |
parent->expectargs = 1; |
parent->expectargs = 1; |
parent->font = EQNFONT_ROMAN; |
parent->font = EQNFONT_ROMAN; |
switch (tok) { |
switch (tok) { |
|
|
* exactly one of those. |
* exactly one of those. |
*/ |
*/ |
parent = eqn_box_alloc(ep, parent); |
parent = eqn_box_alloc(ep, parent); |
parent->type = EQN_LISTONE; |
parent->type = EQN_LIST; |
parent->expectargs = 1; |
parent->expectargs = 1; |
switch (tok) { |
switch (tok) { |
case EQN_TOK_FAT: |
case EQN_TOK_FAT: |
|
|
ep->gsize = size; |
ep->gsize = size; |
break; |
break; |
} |
} |
|
while (parent->args == parent->expectargs) |
|
parent = parent->parent; |
parent = eqn_box_alloc(ep, parent); |
parent = eqn_box_alloc(ep, parent); |
parent->type = EQN_LISTONE; |
parent->type = EQN_LIST; |
parent->expectargs = 1; |
parent->expectargs = 1; |
parent->size = size; |
parent->size = size; |
break; |
break; |
|
|
cur->type = EQN_TEXT; |
cur->type = EQN_TEXT; |
cur->text = mandoc_strdup(""); |
cur->text = mandoc_strdup(""); |
} |
} |
/* Handle the "subsup" and "fromto" positions. */ |
while (parent->expectargs == 1 && parent->args == 1) |
if (EQN_TOK_SUP == tok && parent->pos == EQNPOS_SUB) { |
parent = parent->parent; |
|
if (tok == EQN_TOK_FROM || tok == EQN_TOK_TO) { |
|
for (cur = parent; cur != NULL; cur = cur->parent) |
|
if (cur->pos == EQNPOS_SUB || |
|
cur->pos == EQNPOS_SUP || |
|
cur->pos == EQNPOS_SUBSUP || |
|
cur->pos == EQNPOS_SQRT || |
|
cur->pos == EQNPOS_OVER) |
|
break; |
|
if (cur != NULL) |
|
parent = cur->parent; |
|
} |
|
if (tok == EQN_TOK_SUP && parent->pos == EQNPOS_SUB) { |
parent->expectargs = 3; |
parent->expectargs = 3; |
parent->pos = EQNPOS_SUBSUP; |
parent->pos = EQNPOS_SUBSUP; |
break; |
break; |
} |
} |
if (EQN_TOK_TO == tok && parent->pos == EQNPOS_FROM) { |
if (tok == EQN_TOK_TO && parent->pos == EQNPOS_FROM) { |
parent->expectargs = 3; |
parent->expectargs = 3; |
parent->pos = EQNPOS_FROMTO; |
parent->pos = EQNPOS_FROMTO; |
break; |
break; |
} |
} |
|
parent = eqn_box_makebinary(ep, parent); |
switch (tok) { |
switch (tok) { |
case EQN_TOK_FROM: |
case EQN_TOK_FROM: |
pos = EQNPOS_FROM; |
parent->pos = EQNPOS_FROM; |
break; |
break; |
case EQN_TOK_TO: |
case EQN_TOK_TO: |
pos = EQNPOS_TO; |
parent->pos = EQNPOS_TO; |
break; |
break; |
case EQN_TOK_SUP: |
case EQN_TOK_SUP: |
pos = EQNPOS_SUP; |
parent->pos = EQNPOS_SUP; |
break; |
break; |
case EQN_TOK_SUB: |
case EQN_TOK_SUB: |
pos = EQNPOS_SUB; |
parent->pos = EQNPOS_SUB; |
break; |
break; |
default: |
default: |
abort(); |
abort(); |
} |
} |
parent = eqn_box_makebinary(ep, pos, parent); |
|
break; |
break; |
case EQN_TOK_SQRT: |
case EQN_TOK_SQRT: |
while (parent->args == parent->expectargs) |
while (parent->args == parent->expectargs) |
|
|
cur->type = EQN_TEXT; |
cur->type = EQN_TEXT; |
cur->text = mandoc_strdup(""); |
cur->text = mandoc_strdup(""); |
} |
} |
|
while (parent->args == parent->expectargs) |
|
parent = parent->parent; |
while (EQN_SUBEXPR == parent->type) |
while (EQN_SUBEXPR == parent->type) |
parent = parent->parent; |
parent = parent->parent; |
parent = eqn_box_makebinary(ep, EQNPOS_OVER, parent); |
parent = eqn_box_makebinary(ep, parent); |
|
parent->pos = EQNPOS_OVER; |
break; |
break; |
case EQN_TOK_RIGHT: |
case EQN_TOK_RIGHT: |
case EQN_TOK_BRACE_CLOSE: |
case EQN_TOK_BRACE_CLOSE: |
|
|
*/ |
*/ |
for (cur = parent; cur != NULL; cur = cur->parent) |
for (cur = parent; cur != NULL; cur = cur->parent) |
if (cur->type == EQN_LIST && |
if (cur->type == EQN_LIST && |
|
cur->expectargs > 1 && |
(tok == EQN_TOK_BRACE_CLOSE || |
(tok == EQN_TOK_BRACE_CLOSE || |
cur->left != NULL)) |
cur->left != NULL)) |
break; |
break; |
|
|
parent->type == EQN_MATRIX)) |
parent->type == EQN_MATRIX)) |
parent = parent->parent; |
parent = parent->parent; |
/* Close out any "singleton" lists. */ |
/* Close out any "singleton" lists. */ |
while (parent->type == EQN_LISTONE && |
while (parent->type == EQN_LIST && |
parent->args == parent->expectargs) |
parent->expectargs == 1 && |
|
parent->args == 1) |
parent = parent->parent; |
parent = parent->parent; |
break; |
break; |
case EQN_TOK_BRACE_OPEN: |
case EQN_TOK_BRACE_OPEN: |
|
|
parent = split->parent; |
parent = split->parent; |
break; |
break; |
} |
} |
/* |
|
* Post-process list status. |
|
*/ |
|
while (parent->type == EQN_LISTONE && |
|
parent->args == parent->expectargs) |
|
parent = parent->parent; |
|
break; |
break; |
default: |
default: |
abort(); |
abort(); |