% This file is part of AceWiki. % Copyright 2008-2012, AceWiki developers. % % AceWiki is free software: you can redistribute it and/or modify it under the terms of the GNU % Lesser General Public License as published by the Free Software Foundation, either version 3 of % the License, or (at your option) any later version. % % AceWiki is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without % even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU % Lesser General Public License for more details. % % You should have received a copy of the GNU Lesser General Public License along with AceWiki. If % not, see http://www.gnu.org/licenses/. :- module(generate_html, [ generate_html/2 % +InputFile, +OutputFile ]). /** Generate HTML Representation This module transfroms from the Codeco format into an HTML representation. Usage: == swipl -s generate_html.pl -g "generate_html('my_codeco_grammar.pl', 'my_html_file.html')" -t halt == You may have to replace "swipl" by the name of your SWI Prolog executable. Before transforming a file, you should make sure that it is a well-formed Codeco file: == swipl -s validate_codeco.pl -g "validate_codeco('my_codeco_grammar.pl')" -t halt == For more information about Codeco, see the following thesis: http://attempto.ifi.uzh.ch/site/pubs/papers/doctoral_thesis_kuhn.pdf @author Tobias Kuhn @version 2010-10-18 */ % Codeco operator definitions: :- op(1200, xfx, '=>'). :- op(1200, xfx, '~>'). :- op(600, xfx, ':'). :- op(500, yfx, '+'). :- op(300, fx, '$'). :- op(300, fx, '#'). :- op(0, fx, '+'). % Remove declaration :- op(0, xfx, '>'). % Remove declaration :- op(0, xfx, '<'). % Remove declaration %% sort_features(?OnOff) % % This fact defines whether the features should be shown in alphabetical order ('on') or in the % same order as they appear in the input file ('off'). %sort_features(off). sort_features(on). %% generate_html(+InputFile, +OutputFile) % % This predicate reads the Codeco grammar from the input file and transforms it into an HTML file. generate_html(InputFile, OutputFile) :- retractall(next_id(_)), assert(next_id(1)), open(InputFile, read, In), open(OutputFile, write, Out), header(Header), write(Out, Header), ( process(In, Out) ; write(user_error, 'Error during parsing.\n') ), close(In), footer(Footer), write(Out, Footer), close(Out). process(In, Out) :- read_term(In, Term, [module(generate_html)]), ( Term == end_of_file -> true ; retractall(var_number(_, _)), numbervars(Term, 1, _), process_term(Out, Term), process(In, Out) ). process_term(Out, title:T) :- !, format(Out, '

~l

\n', [T]). process_term(Out, section:S) :- !, format(Out, '

~l

\n', [S]). process_term(Out, paragraph:P) :- !, format(Out, '

~l

\n', [P]). process_term(Out, Head => Body) :- !, get_category_name(Head, N), write(Out, '\n'), write_id(Out), process_head(Out, Head), format(Out, '\n', N), process_cats(Out, Body), write(Out, '
=>
\n\n'). process_term(Out, Head ~> Body) :- !, get_category_name(Head, N), write(Out, '\n'), write_id(Out), process_head(Out, Head), format(Out, '\n', N), process_cats(Out, Body), write(Out, '
~~>
\n\n'). process_term(_, Term) :- format(user_error, 'WARNING. Cannot process term: ~q\n', Term). process_head(Out, _ : Cond) :- !, process_cat(Out, Cond). process_head(Out, Cond) :- process_cat(Out, Cond). process_cats(Out, Body) :- Body = ','(Cat, BodyRest), !, process_cat(Out, Cat), process_cats(Out, BodyRest). process_cats(_, []) :- !. process_cats(Out, BodyLast) :- process_cat(Out, BodyLast). process_cat(_, []) :- !. process_cat(Out, [T|Rest]) :- T =.. [Name], !, format(Out, ' [ ~l ]\n', Name), process_cat(Out, Rest). process_cat(Out, $ Cat) :- Cat =.. [Name], !, format(Out, ' ~l\n', [Name,Name]). process_cat(Out, $ Cat) :- Cat =.. [Name|Features], !, format(Out, ' ~l', [Name,Name]), process_features(Out, Features), write(Out, '
\n'). process_cat(Out, # '$VAR'(V)) :- !, get_var_number(V, N), format(Out, ' #~l\n', N). process_cat(Out, '//') :- !, write(Out, ' //\n'). process_cat(Out, Cat) :- Cat =.. [Name], !, format(Out, ' ~l\n', [Name,Name]). process_cat(Out, Cat) :- Cat =.. ['>'|Features], !, write(Out, ' >'), process_features(Out, Features), write(Out, '
\n'). process_cat(Out, Cat) :- Cat =.. ['>>'|Features], !, write(Out, ' >>'), process_features(Out, Features), write(Out, '
\n'). process_cat(Out, Cat) :- Cat =.. ['<'|BwrefTerms], \+ BwrefTerms = [], \+ member(_:_, BwrefTerms), !, write(Out, ' <+'), process_bwrefterms(Out, BwrefTerms), write(Out, ' \n'). process_cat(Out, Cat) :- Cat =.. ['<'|Features], !, write(Out, ' <'), process_features(Out, Features), write(Out, '
\n'). process_cat(Out, Cat) :- Cat =.. ['/<'|Features], !, write(Out, ' /<'), process_features(Out, Features), write(Out, '
\n'). process_cat(Out, Cat) :- Cat =.. [Name|Features], format(Out, ' ~l', [Name,Name]), process_features(Out, Features), write(Out, '
\n'). process_bwrefterms(Out, [Term|Rest]) :- Term =.. ['+'|Features], !, write(Out, ' '), process_features(Out, Features), write(Out, '
'), process_bwrefterms(Out, Rest). process_bwrefterms(Out, Terms) :- write(Out, ' –'), process_bwrefterms_x(Out, Terms). process_bwrefterms_x(Out, [Term|Rest]) :- Term =.. ['-'|Features], !, write(Out, ' '), process_features(Out, Features), write(Out, '
'), process_bwrefterms_x(Out, Rest). process_bwrefterms_x(_, []). process_features(Out, Features) :- sort_features(on), !, sort(Features, FeaturesS), process_features_x(Out, FeaturesS). process_features(Out, Features) :- process_features_x(Out, Features). process_features_x(_, []). process_features_x(Out, [Name:'$VAR'(V)|Rest]) :- !, get_var_number(V, N), format(Out, '~l: ~l ', [Name, N]), process_features_x(Out, Rest). process_features_x(Out, [Name:plus|Rest]) :- !, format(Out, '~l: +', [Name]), process_features_x(Out, Rest). process_features_x(Out, [Name:minus|Rest]) :- !, format(Out, '~l: ', [Name]), process_features_x(Out, Rest). process_features_x(Out, [Name:Value|Rest]) :- !, format(Out, '~l: ~l', [Name, Value]), process_features_x(Out, Rest). get_category_name(C, N) :- C =.. [$,P], !, P =.. [NN|_], atom_concat('_', NN, N). get_category_name(_:C, N) :- !, get_category_name(C, N). get_category_name(C, N) :- C =.. [N|_]. :- dynamic(next_id/1). write_id(Out) :- next_id(ID), format(Out, ' (~w)\n', ID), retractall(next_id(_)), NewID is ID + 1, assert(next_id(NewID)). :- dynamic(var_number/2). get_var_number(VarID, VarNumber) :- var_number(VarID, VarNumber), !. get_var_number(VarID, VarNumber) :- var_number(_, LastVarNumber), !, VarNumber is LastVarNumber + 1, asserta(var_number(VarID, VarNumber)). get_var_number(VarID, 1) :- asserta(var_number(VarID, 1)). replace(Input, Search, Replace, Output) :- concat_atom(Split, Search, Input), concat_atom(Split, Replace, Output). :- format_predicate(l, write_html(_Arg, _Term)). write_html(_, Atom) :- replace(Atom, '&', '&', Atom1), replace(Atom1, '<', '<', Atom2), replace(Atom2, '>', '>', Atom3), write(Atom3). :- style_check(-atom). header(' Codeco Grammar '). footer(' ').