Skip to content

Commit

Permalink
moved ANSI highlighter feature from Box2Tex to util::Highlighter. Thi…
Browse files Browse the repository at this point in the history
…s commit also refactors toHTML and toLaTeX for readability and speed and removes some dead code
  • Loading branch information
jurgenvinju committed Apr 1, 2024
1 parent a1ed555 commit 4ec236f
Showing 1 changed file with 128 additions and 56 deletions.
184 changes: 128 additions & 56 deletions src/org/rascalmpl/library/util/Highlight.rsc
Original file line number Diff line number Diff line change
@@ -1,84 +1,156 @@

@license{
Copyright (c) 2013-2024 CWI
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
which accompanies this distribution, and is available at
http://www.eclipse.org/legal/epl-v10.html
}
@contributor{[email protected]}
@contributor{[email protected]}
@synopsis{Maps parse trees to highlighting markup in ANSI, HTML or LaTeX format.}
module util::Highlight

import ParseTree;
import String;
import IO;

@synopsis{Yields the characters of a parse tree as the original input sentence in a <code>...</code> block, but with spans for highlighted segments in HTML}
public str ToHTML(Tree t) {
htmlEscapes = (
"\<": "&lt;",
"\>": "&gt;",
"&" : "&amp;"
);

str rec(t:appl(prod(lit(str l), _, _), _))
= span("Keyword", l) when isKeyword(l);

str rec(t:appl(prod(cilit(str l), _, _), _))
= span("Keyword", l) when isKeyword(l);

str rec(t:appl(prod(_, _, {*_, \tag("category"(str cat))}), list[Tree] as))
= span(cat, "<for (a <- as) {><rec(a)><}>");

default str rec(appl(_, list[Tree] as))
= "<for (a <- as) {><rec(a)><}>";

str rec(amb({k, *_})) = rec(k);

default str rec(Tree t:char(_)) = escape("<t>", htmlEscapes);

str span(str class, str src) = "\<span class=\"<class>\"\><src>\</span\>";

return "\<pre class=\"rascal\"\>\<code\><trim(rec(t))>\</code\>\</pre\>";
}

@synopsis{Yields the characters of a parse tree as the original input sentence but using macros to wrap to-be-highlighted areas.}
public str toLaTeX(Tree t) {
texEscapes = (
"\\": "\\textbackslash{}",
"\<": "\\textless{}",
"\>": "\\textgreater{}",
"%": "\\%{}",
"&" : "\\&{}",
"_" : "\\_{}",
"^" : "\\^{}",
"{" : "\\{{}",
"}" : "\\}{}",
"$" : "\\${}",
"[" : "{}[",
"\t" : " "
);

str rec(appl(prod(lit(str l), _, _), _)) = cat("Keyword", l)
when isKeyword(l);

str rec(appl(prod(cilit(str l), _, _), _)) = cat("Keyword", l)
when isKeyword(l);

str rec(appl(prod(_, _, {*_, \tag("category"(str category))}), list[Tree] as))
= cat(category, "<for (a <- as) {><rec(a)><}>");

// A comment
default str rec(appl(_, list[Tree] as))
= "<for (a <- as) {><rec(a)><}>";

str rec(amb({k, *_})) = rec(k);

public map[str, str] htmlEscapes = (
"\<": "&lt;",
"\>": "&gt;",
"&" : "&amp;"
);
default str rec(Tree t:char(_)) = escape("<t>", texEscapes);

str cat(str class, str src) = "\\CAT{<class>}{<src>}";

str highlight2html(Tree t)
= "\<pre class=\"rascal\"\>\<code\><trim(highlight2htmlRec(t))>\</code\>\</pre\>";
return rec(t);
}

bool isKeyword(str s) = /^[a-zA-Z0-9_\-]*$/ := s;
@synopsis{Yields the characters of a parse tree as the original input sentence in a <code>...</code> block, but with spans for highlighted segments in HTML}
public str toHTML(Tree t) {
htmlEscapes = (
"\<": "&lt;",
"\>": "&gt;",
"&" : "&amp;"
);

str highlight2htmlRec(t:appl(prod(lit(str l), _, _), _))
= wrapLink(span("Keyword", l), t)
when isKeyword(l);
str rec(t:appl(prod(lit(str l), _, _), _))
= wrapLink(span("Keyword", l), t)
when isKeyword(l);

str highlight2htmlRec(t:appl(prod(cilit(str l), _, _), _))
= wrapLink(span("Keyword", l), t)
when isKeyword(l);
str rec(t:appl(prod(cilit(str l), _, _), _))
= wrapLink(span("Keyword", l), t)
when isKeyword(l);

str highlight2htmlRec(t:appl(prod(_, _, {*_, \tag("category"(str cat))}), list[Tree] as))
= wrapLink(span(cat, ( "" | it + highlight2htmlRec(a) | a <- as )), t);
str rec(t:appl(prod(_, _, {*_, \tag("category"(str cat))}), list[Tree] as))
= wrapLink(span(cat, ( "" | it + rec(a) | a <- as )), t);

str highlight2htmlRec(appl(prod(_, _, set[Attr] attrs), list[Tree] as))
= ( "" | it + highlight2htmlRec(a) | a <- as )
when {*_, \tag("category"(str _))} !:= attrs;
str rec(appl(prod(_, _, set[Attr] attrs), list[Tree] as))
= ( "" | it + rec(a) | a <- as )
when {*_, \tag("category"(str _))} !:= attrs;

str highlight2htmlRec(appl(regular(_), list[Tree] as))
= ( "" | it + highlight2htmlRec(a) | a <- as );
str rec(appl(regular(_), list[Tree] as))
= ( "" | it + rec(a) | a <- as );

str highlight2htmlRec(amb({k, *_})) = highlight2htmlRec(k);
str rec(amb({k, *_})) = rec(k);

default str highlight2htmlRec(Tree t)
= wrapLink(escape(unparse(t), htmlEscapes), t);
default str rec(Tree t)
= wrapLink(escape(unparse(t), htmlEscapes), t);

str span(str class, str src) = "\<span class=\"<class>\"\><src>\</span\>";
str span(str class, str src) = "\<span class=\"<class>\"\><src>\</span\>";

default str wrapLink(str text, Tree _) = text;
default str wrapLink(str text, Tree _) = text;

// Latex
return "\<pre class=\"rascal\"\>\<code\><trim(rec(t))>\</code\>\</pre\>";
}

public map[str, str] texEscapes = (
"\\": "\\textbackslash{}",
"\<": "\\textless{}",
"\>": "\\textgreater{}",
"%": "\\%{}",
"&" : "\\&{}",
"_" : "\\_{}",
"^" : "\\^{}",
"{" : "\\{{}",
"}" : "\\}{}",
"$" : "\\${}",
"[" : "{}[",
"\t" : " "
);
@synopsis{Unparse a parse tree to unicode characters, wrapping certain substrings with ANSI codes for highlighting.}
public str toANSI(Tree t, bool underlineAmbiguity=false, int tabSize=4) {
str rec(Tree x:appl(prod(lit(str l), _, _), _)) = isKeyword(l) ? bold("<x>") : "<x>";
str rec(Tree x:appl(prod(cilit(str l), _, _), _)) = isKeyword(l) ? bold("<x>") : "<x>";

str highlight2latex(appl(prod(lit(str l), _, _), _)) = catCmd("Keyword", l)
when isKeyword(l);
str rec(Tree x:appl(prod(_, _, {*_, \tag("category"(str cat))}), list[Tree] as))
= \map(cat, "<x>");

str highlight2latex(appl(prod(cilit(str l), _, _), _)) = catCmd("Keyword", l)
when isKeyword(l);
default str rec(x:appl(_, list[Tree] as))
= "<for (a <- as) {><rec(a)><}>";

str highlight2latex(appl(prod(_, _, {*_, \tag("category"(str cat))}), list[Tree] as))
= catCmd(cat, ( "" | it + highlight2latex(a) | a <- as ));
str rec(amb({k, *_})) = underlineAmbiguity ? underline(rec(k)) : rec(k);

str highlight2latex(appl(prod(_, _, set[Attr] attrs), list[Tree] as))
= ( "" | it + highlight2latex(a) | a <- as )
when {*_, \tag("category"(str _))} !:= attrs;
str rec (char(9)) = right("", tabSize);
default str rec(Tree t:char(_)) = "<t>";

str highlight2latex(appl(regular(_), list[Tree] as))
= ( "" | it + highlight2latex(a) | a <- as );
str ESC = "\a1b[";
str Bold = "<ESC>1m";
str Underline = "<ESC>4m";
str Normal = "<ESC>0m";
str Comment = "<ESC>3m<ESC>2m";
str bold(str s) = "<Bold><s><Normal>";
str underline(str s) = "<Underline><s><Normal>";
str comment(str s) = "<Comment><s><Normal>";

str highlight2latex(amb({k, *_})) = highlight2latex(k);
str \map("Comment", text) = comment(text);
str \map("Keyword", text) = bold(text);
default str \map(str _, str text) = text;

default str highlight2latex(Tree t) = escape(unparse(t), texEscapes);
return rec(t);
}

str catCmd(str class, str src) = "\\CAT{<class>}{<src>}";
@synopsis{Encodes when to highlight a literal as a keyword category}
private bool isKeyword(str s) = /^[a-zA-Z0-9_\-]*$/ := s;

0 comments on commit 4ec236f

Please sign in to comment.