120 lines
3.5 KiB
Vala
120 lines
3.5 KiB
Vala
|
namespace LAview {
|
||
|
|
||
|
namespace Parsers {
|
||
|
|
||
|
using Table;
|
||
|
|
||
|
class LongtableParser : TableParser {
|
||
|
|
||
|
public LongtableParser (Array<Link> links) {
|
||
|
base (links);
|
||
|
}
|
||
|
|
||
|
public override IDoc parse (string contents, size_t line, long position) throws ParseError {
|
||
|
|
||
|
/* create empty longtable */
|
||
|
var longtable = new Longtable ();
|
||
|
|
||
|
/* set TeX longtable contents */
|
||
|
this.contents = contents;
|
||
|
this.line = line;
|
||
|
this.position = position;
|
||
|
|
||
|
/* get parameters string */
|
||
|
var param_regex = "^(\\[(c|l|r)])?\\{[^{}]*([^{}]*\\{[^{}]*\\}[^{}]*)*\\}";
|
||
|
|
||
|
string params = "";
|
||
|
|
||
|
try {
|
||
|
var regex = new Regex (param_regex);
|
||
|
|
||
|
MatchInfo match_info;
|
||
|
regex.match (contents, 0, out match_info);
|
||
|
|
||
|
uint start_pos = 0, stop_pos = 0;
|
||
|
|
||
|
if (match_info.matches ()) {
|
||
|
match_info.fetch_pos (0, out start_pos, out stop_pos);
|
||
|
/* set TeX document contents */
|
||
|
this.contents = contents.offset (stop_pos);
|
||
|
params = match_info.fetch (0);
|
||
|
} else {
|
||
|
/// Translators: please leave the '%s' construction without any changes.
|
||
|
prefix_error (subdoc_start,
|
||
|
_("Incorrect longtable parameters doesn't match '%s' regexp."),
|
||
|
param_regex);
|
||
|
throw new ParseError.SUBDOC (err_str);
|
||
|
}
|
||
|
} catch (RegexError e) {}
|
||
|
|
||
|
/* longtable align: [c], [l], [r] */
|
||
|
if (params[0] == '[') {
|
||
|
longtable.align = params[1];
|
||
|
params = params.offset (3);
|
||
|
}
|
||
|
|
||
|
/* remove bound '{' '}' from params */
|
||
|
params = params.substring (1, params.length - 2).reverse ();
|
||
|
var col_params = new ColParams ();
|
||
|
|
||
|
/* match reversed params so '|' will be snapped to the right column */
|
||
|
try {
|
||
|
var regex = new Regex ("("
|
||
|
+ "\\|*}[^{}]+{(p\\|*|m\\|*|b\\|*)(}[^{}]+{>(\\|+$|\\||)|\\|)?"
|
||
|
+ "|"
|
||
|
+ "\\|*(r|c|l)(}[^{}]+{@(p\\|*|m\\|*|b\\|*) (r|c|l))?(\\|+$|\\||)"
|
||
|
+ ")");
|
||
|
MatchInfo match_info;
|
||
|
regex.match_full (params, -1, 0, 0, out match_info);
|
||
|
while (match_info.matches ()) {
|
||
|
var col_param = new ColParam.with_params (0, "", 0);
|
||
|
var word = match_info.fetch (0).reverse ().compress ();
|
||
|
int nllines, nrlines;
|
||
|
for (nllines = 0; '|' == word[nllines]; ++nllines);
|
||
|
for (nrlines = word.length - 1; nrlines != 0 && '|' == word[nrlines]; --nrlines);
|
||
|
var wlen = word.length;
|
||
|
word = word[0:nrlines + 1];
|
||
|
col_param.align = word.offset (nllines);
|
||
|
col_param.nllines = nllines;
|
||
|
col_param.nrlines = wlen - 1 - nrlines;
|
||
|
col_params.insert (0, col_param);
|
||
|
match_info.next ();
|
||
|
}
|
||
|
} catch (RegexError e) {}
|
||
|
|
||
|
longtable.params = col_params;
|
||
|
|
||
|
/* === Parsing subtables === */
|
||
|
|
||
|
/* feed in the text */
|
||
|
scanner.input_text (this.contents, this.contents.length);
|
||
|
|
||
|
row_abs_pos = 0;
|
||
|
row = new Row ();
|
||
|
subtable = new Subtable ();
|
||
|
in_caption = false;
|
||
|
cell_abs_pos = 0;
|
||
|
|
||
|
TokenType expected_token = TokenType.NONE;
|
||
|
|
||
|
/* scanning loop, we scan the input until it's end is reached,
|
||
|
* the self encountered a lexing err, or our sub routine came
|
||
|
* across invalid syntax
|
||
|
*/
|
||
|
do {
|
||
|
expected_token = scan_tex_symbol (longtable);
|
||
|
|
||
|
} while (expected_token == TokenType.NONE
|
||
|
&& fifo_peek_head ().token != TokenType.EOF
|
||
|
&& fifo_peek_head ().token != TokenType.ERROR);
|
||
|
|
||
|
/* give an err message upon syntax errors */
|
||
|
if (expected_token == TokenType.ERROR)
|
||
|
scanner.unexp_token (expected_token, null, "symbol", null, null, true);
|
||
|
|
||
|
return longtable;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|