Mercurial > blahgd > fmt4
changeset 1163:c53e5eb4a4aa
post fmt3: use presentation MathML to render math equations
Instead of shelling out to LaTeX, we can transform the TeX math into MathML
and send it to the browser ourselves.
Signed-off-by: Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
author | Josef 'Jeff' Sipek <jeffpc@josefsipek.net> |
---|---|
date | Tue, 22 Jan 2019 19:17:20 -0500 |
parents | 5eed88560af7 |
children | 76e18831873f |
files | post_fmt3.l post_fmt3.y |
diffstat | 2 files changed, 55 insertions(+), 28 deletions(-) [+] |
line wrap: on
line diff
--- a/post_fmt3.l Sun Jan 27 13:01:41 2019 -0500 +++ b/post_fmt3.l Tue Jan 22 19:17:20 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2011-2019 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -77,11 +77,14 @@ "$" { BEGIN(MATH); return MATHSTART; } <MATH>"$" { BEGIN(INITIAL); return MATHEND; } +<MATH>"frac" { return MATHFRAC; } +<MATH>"sqrt" { return MATHSQRT; } +<MATH>"propto" { return MATHPROPTO; } <MATH>[\\{}()*/~^_+-] { return *yytext; } -<MATH>[=<>] { yylval->ptr = STR_DUP(yytext); return EQLTGT; } -<MATH>[A-Za-z0-9]+ { yylval->ptr = STR_DUP(yytext); return WORD; } -<MATH>[".,=<>!:;?@*#] { yylval->ptr = STR_DUP(yytext); return SCHAR; } -<MATH>[ \t]+ { yylval->ptr = STR_DUP(yytext); return WSPACE; } +<MATH>[=<>] { return *yytext; } +<MATH>[A-Za-z]+ { yylval->ptr = STR_DUP(yytext); return WORD; } +<MATH>[0-9.]+ { yylval->ptr = STR_DUP(yytext); return NUMBER; } +<MATH>[ \t]+ { continue; /* skip whitespace */ } <MATH>. { fmt3_error2("post math contains invalid characters", yytext); yyterminate(); } "\\$" { return DOLLAR; }
--- a/post_fmt3.y Sun Jan 27 13:01:41 2019 -0500 +++ b/post_fmt3.y Tue Jan 22 19:17:20 2019 -0500 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2018 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> + * Copyright (c) 2011-2019 Josef 'Jeff' Sipek <jeffpc@josefsipek.net> * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -136,6 +136,21 @@ *var = VAL_ALLOC_CONS(str_cast_to_val(value), *var); } +static struct str *math_apply(struct str *op, struct str *a, struct str *b) +{ + str_getref(op); + if (b) + return str_cat(9, + STATIC_STR("<"), op, STATIC_STR("><mrow>"), + a, STATIC_STR("</mrow><mrow>"), b, + STATIC_STR("</mrow></"), op, STATIC_STR(">")); + else + return str_cat(7, + STATIC_STR("<"), op, STATIC_STR("><mrow>"), + a, + STATIC_STR("</mrow></"), op, STATIC_STR(">")); +} + %} %union { @@ -145,13 +160,14 @@ /* generic tokens */ %token <ptr> WSPACE %token <ptr> DASH OQUOT CQUOT SCHAR CHAR -%token <ptr> UTF8CHAR WORD +%token <ptr> UTF8CHAR WORD NUMBER %token PERCENT ELLIPSIS %token PAREND /* math specific tokens */ -%token <ptr> EQLTGT %token MATHSTART MATHEND +%token MATHFRAC MATHSQRT +%token MATHPROPTO /* verbose & listing environment */ %token <ptr> VERBTEXT @@ -164,11 +180,11 @@ %type <ptr> paragraphs paragraph thing cmd cmdarg optcmdarg math mexpr %type <ptr> verb +%left '=' '<' '>' +%left '*' '/' +%left '+' '-' %left '_' '^' %left '~' -%left EQLTGT -%left '+' '-' -%left '*' '/' %% @@ -200,7 +216,7 @@ | DOLLAR { $$ = STATIC_STR("$"); } | PERCENT { $$ = STATIC_STR("%"); } | '\\' cmd { $$ = $2; } - | MATHSTART math MATHEND { $$ = render_math($2); } + | MATHSTART math MATHEND { $$ = str_cat(3, STATIC_STR("<math>"), $2, STATIC_STR("</math>")); } | VERBSTART verb VERBEND { $$ = str_cat(3, STATIC_STR("</p>"), $2, STATIC_STR("<p>")); } | LISTSTART verb LISTEND { $$ = str_cat(3, STATIC_STR("</p><pre>"), listing_str($2), @@ -242,22 +258,30 @@ | mexpr { $$ = $1; } ; -mexpr : WORD { $$ = $1; } - | WSPACE { $$ = $1; } - | CHAR { $$ = $1; } - | SCHAR { $$ = $1; } - | mexpr EQLTGT mexpr { $$ = str_cat(3, $1, $2, $3); } - | mexpr '_' mexpr { $$ = str_cat(3, $1, STATIC_STR("_"), $3); } - | mexpr '^' mexpr { $$ = str_cat(3, $1, STATIC_STR("^"), $3); } - | mexpr '+' mexpr { $$ = str_cat(3, $1, STATIC_STR("+"), $3); } - | mexpr '-' mexpr { $$ = str_cat(3, $1, STATIC_STR("-"), $3); } - | mexpr '*' mexpr { $$ = str_cat(3, $1, STATIC_STR("*"), $3); } - | mexpr '/' mexpr { $$ = str_cat(3, $1, STATIC_STR("/"), $3); } - | mexpr '~' mexpr { $$ = str_cat(3, $1, STATIC_STR("~"), $3); } - | '\\' WORD { $$ = str_cat(2, STATIC_STR("\\"), $2); } - | '\\' '_' { $$ = STATIC_STR("\\_"); } - | '(' math ')' { $$ = str_cat(3, STATIC_STR("("), $2, STATIC_STR(")")); } - | '{' math '}' { $$ = str_cat(3, STATIC_STR("{"), $2, STATIC_STR("}")); } +mexpr : mexpr '+' mexpr { $$ = str_cat(3, $1, STATIC_STR("<mo>+</mo>"), $3); } + | mexpr '-' mexpr { $$ = str_cat(3, $1, STATIC_STR("<mo>-</mo>"), $3); } + | mexpr '*' mexpr { $$ = str_cat(3, $1, STATIC_STR("<mo>*</mo>"), $3); } + | mexpr '/' mexpr { $$ = str_cat(3, $1, STATIC_STR("<mo>/</mo>"), $3); } + | mexpr '^' mexpr { $$ = math_apply(STATIC_STR("msup"), $1, $3); } + | mexpr '_' mexpr { $$ = math_apply(STATIC_STR("msub"), $1, $3); } + | mexpr '=' mexpr { $$ = str_cat(3, $1, STATIC_STR("<mo>=</mo>"), $3); } + | mexpr '<' mexpr { $$ = str_cat(3, $1, STATIC_STR("<mo><</mo>"), $3); } + | mexpr '>' mexpr { $$ = str_cat(3, $1, STATIC_STR("<mo>></mo>"), $3); } + | mexpr '~' mexpr { $$ = str_cat(2, $1, $3); } + | '(' mexpr ')' { $$ = str_cat(3, + STATIC_STR("<mrow><mo>(</mo><mrow>"), + $2, + STATIC_STR("</mrow><mo>)</mo></mrow>")); } + | '{' mexpr '}' { $$ = $2; } + | '\\' MATHFRAC '{' mexpr '}' '{' mexpr '}' + { $$ = math_apply(STATIC_STR("mfrac"), $4, $7); } + | '\\' MATHSQRT '{' mexpr '}' { $$ = math_apply(STATIC_STR("msqrt"), $4, NULL); } + | '\\' MATHPROPTO { $$ = STATIC_STR("<mo>∝</mo>"); } + | NUMBER { $$ = str_cat(3, STATIC_STR("<mn>"), $1, STATIC_STR("</mn>")); } + | WORD { $$ = str_cat(3, STATIC_STR("<mi>"), $1, STATIC_STR("</mi>")); } + | MATHFRAC { $$ = STATIC_STR("<mi>frac</mi>"); } + | MATHSQRT { $$ = STATIC_STR("<mi>sqrt</mi>"); } + | MATHPROPTO { $$ = STATIC_STR("<mi>propto</mi>"); } ; %%