Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

added mowyw to the repository

git-svn-id: svn+ssh://faui2k3.org/var/lib/svn/moritz/mowyw@258 addfbb1e-f4f9-0310-b6f0-bccd0f9b8dc6
  • Loading branch information...
commit 52f3521bf7cf2172137d4ab7726b67a32ba25e18 0 parents
moritz authored
Showing with 1,558 additions and 0 deletions.
  1. +5 −0 Changelog
  2. +115 −0 Mowyw/Lexer.pm
  3. +190 −0 README
  4. +13 −0 TODO
  5. +1 −0  example/incl_test
  6. +6 −0 example/includes/footer
  7. +17 −0 example/includes/head2
  8. +8 −0 example/includes/header
  9. +17 −0 example/includes/menu-nav
  10. +9 −0 example/online/.htaccess
  11. +51 −0 example/online/bar.shtml
  12. +58 −0 example/online/foo.shtml
  13. +58 −0 example/online/foo1.shtml
  14. +58 −0 example/online/foo2.shtml
  15. BIN  example/online/images/arrow.gif
  16. BIN  example/online/images/bg.png
  17. BIN  example/online/images/document.gif
  18. +87 −0 example/online/index.shtml
  19. +3 −0  example/online/no-header-footer.shtml
  20. +17 −0 example/online/print.css
  21. +149 −0 example/online/style.css
  22. +9 −0 example/source/.htaccess
  23. +10 −0 example/source/bar.shtml
  24. +10 −0 example/source/foo.shtml
  25. +10 −0 example/source/foo1.shtml
  26. +10 −0 example/source/foo2.shtml
  27. BIN  example/source/images/arrow.gif
  28. BIN  example/source/images/bg.png
  29. BIN  example/source/images/document.gif
  30. +46 −0 example/source/index.shtml
  31. +3 −0  example/source/no-header-footer.shtml
  32. +17 −0 example/source/print.css
  33. +149 −0 example/source/style.css
  34. +20 −0 lexer_test.pl
  35. +412 −0 mowyw
5 Changelog
@@ -0,0 +1,5 @@
+mowyw (0.2.0)
+ * Mowyw/Lexer.pm: added a separate lexer
+ * mowyw: (nearly) complete rewrite using a recursive-descending parser
+ * README: added description for [[[verbatim foo]]] (arbitrary
+ stuff)[[[endverbatim foo]]]
115 Mowyw/Lexer.pm
@@ -0,0 +1,115 @@
+#!/usr/bin/perl
+use warnings;
+use strict;
+package Mowyw::Lexer;
+
+=pod
+=head1 NAME
+
+Mowyw::Lexer - Simple Lexer
+
+=head1 SYNOPSIS
+
+ use Mowyw::Lexer qw(lex);
+ # suppose you want to parse simple math expressions
+ my @input_tokens = (
+ ['Int', qr/(?:-|\+)?\d+/],
+ ['Op', qr/\+|\*|-|\//],
+ ['Brace_Open', qr/\(/],
+ ['Brace_Close', qr/\)/],
+ ['Whitespace', qr/\s/, sub { return undef; }],
+ );
+ my $text = "-12 * (3+4)";
+ foreach (lex($text, \@input_tokens){
+ my ($name, $text) = @$_;
+ print "Found Token $name: $text\n";
+ }
+
+=head1 DESCRIPTION
+
+Mowyw::Lexer is a simple lexer that breaks up a text into tokens, depenending on the input tokens you provide
+
+The only exported method is lex($$), which expects input text as its first argument and a array ref to list of input tokens.
+
+Each input token consists of a token name (which you can choose freely), a regexwhich matches the desired token, and optionally a reference to a functions that takes the matched token text as its argument. The token text is replaced by the return value of that function. If the function returns undef, that token will not be included in the list of output tokens.
+
+lex() returns a list of output tokens, each output token is a reference to a list which contains the token name and the matched text.
+
+If there is unmatched text, it is returned with the token name UNMATCHED.
+
+=head1 COPYRIGHT AND LICENSE
+
+Copyright (C) 2007 by Moritz Lenz, http://moritz.faui2k3.org, moritz@faui2k3.org
+
+This Program and its Documentation is free software. You may distribute it under the same terms as perl itself.
+
+However all code examples are to be public domain, so you can use it in any way you want to.
+
+=cut
+
+require Exporter;
+our @ISA = qw(Exporter);
+our @EXPORT = qw(lex);
+
+our %EXPORT_TAGS = (":all" => \@EXPORT);
+
+sub lex($$){
+ my ($text, $tokens) = @_;
+ return () unless ($text);
+ my @res;
+ while (length($text) > 0){
+ my $matched = 0;
+ # try to match at the start of $text
+ foreach (@$tokens){
+ my $re = $_->[1];
+ if ($text =~ m#^$re#s){
+ $matched = 1;
+ my $match = $&;
+ die "Each token has to require at least one character; Rule $_->[0] matched Zero!\n" unless (length($match) > 0);
+ if (my $fun = $_->[2]){
+ $match = &$fun($match);
+ }
+ if (defined $match){
+ push @res, [$_->[0], $&];
+ }
+ $text = $';
+ last;
+ }
+ }
+ unless ($matched){
+ # no token matched, look what the closest token is
+# my $remain = substr $text, 0, 30;
+# die "No Token matched the remaining String which starts as $remain\n";
+ my $next_token;
+ my $min = length($text);
+ foreach(@$tokens){
+ my $re = $_->[1];
+ if ($text =~ m#$re#s){
+ if (length($`) < $min){
+ $min = length($`);
+ $next_token = $_;
+ $matched = 1;
+ }
+ }
+ }
+ if ($matched){
+ my $re = $next_token->[1];
+ $text =~ m#$re#;
+ push @res, ['UNMATCHED', $`];
+ my $match = $&;
+ die "Each token has to require at least one character; Rule $_->[0] matched Zero!\n" unless (length($match) > 0);
+ if (my $fun =$next_token->[2]){
+ $match = &$fun($match);
+ }
+ push @res, [$next_token->[0], $match] if (defined $match);
+ $text = $';
+ } else {
+ push @res, ['UNMATCHED', $text];
+# print "END OF FILE IS UNMATCHED: $text\n";
+ $text = "";
+ }
+ }
+ }
+ return @res;
+}
+1;
190 README
@@ -0,0 +1,190 @@
+mowyw - mowyw writes your websites (or: Moritz writes your websites ;-)
+
+For license of this file see the notice at the end of the file
+
+moc is an offline CMS, that means it process sources files and generates
+output files from them, usually HTML files, but php files and others are
+possible as well (with some limitations though).
+
+SYNTAX CHANGE
+-------------
+Version 0.0.3 and before used only double square brackets
+(like [[include foo]]), but I noticed that double closing square brackets
+are part of a typical CDATA declaration in xml files (and xhtml) like this:
+<style type="text/css">
+/*<![CDATA[*/
+ CSS Declarations
+/*]]>*/
+</style>
+
+Now tripple square brackets (like [[[include foo]]]) are used.
+
+
+SHORT HOWTO:
+-----------
+
+choose an empty directory, and there create the three directories
+includes/
+source/
+online/
+
+The `source/' directory contains the source files that will be processed by
+mowyw. Each file in the `source/' directory is mapped to one file in the
+`online/' directory. You should not write files into the `online/' directory
+since they may be deleted or overwritten, and you should not modify existing
+files in that directory since all changes are lost during the next run.
+All files that might be included by others (including menus) should be in the
+`includes' directory.
+
+Now place a file index.html (or whatever you want it to be called) in the
+'source/' directory.
+
+If all your HTML files have a common header/footer, you may want to place them
+in in the files `includes/header' and `includes/footer'.
+
+For example `inlcudes/header' may contain
+
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
+<link rel="stylesheet" type="text/css" media="screen, projection" href="style.css" />
+<link rel="stylesheet" type="text/css" media="print" href="print.css" />
+
+and `inlcudes/footer' may contain
+
+ </body>
+</html>
+
+and perhaps an additional footer line to be displayed in all pages.
+
+Now write some content in the file `source/index.html' and then run mowyw.
+You should get an output like that:
+
+Processing File 'source/index.html'... DONE.
+
+Now point your browser at source/index.html and see if it worked.
+Files not ending in .html, .htm, .shtml, .xhtml etc. are not processed, just
+copyied.
+
+
+INCLUDES:
+
+So far mowyw didn't do much work for you, it just added header and footer
+sections to all html files.
+But it can do more for you: includes.
+Just use the line
+
+[[[include foo]]]
+
+in your files, and the line will be replaced with the content of the file
+`includes/foo'. It works pretty much like #inlcude "includes/foo" with a C pre
+processor or <!-- #include virtual="includes/foo"--> with Server Side Includes
+(SSI).
+
+MENUS:
+
+Suppose you want to write a navigation menu in your html files that look like
+this:
+
+menu
+ |
+ +-- foo
+ |
+ +-- bar
+ |
+ +-- baz
+
+and if you click on foo, a sub menu opens:
+
+menu
+ |
+ +-- foo
+ | |
+ | +-foo1
+ | +-foo2
+ | +-foo3
+ |
+ +-- bar
+ |
+ +-- baz
+
+The way you do this with mowyw is simple:
+create a file called `includes/menu-navigation' and fill it with something
+like this:
+
+<div class="menu">
+Navigation:
+<ul>
+ [[[item foo <li><a href="foo.html" {{class="#active"}}>foo</a>
+ {{<ul>
+ <li><a href="foo1">foo1</a></li>
+ <li><a href="foo2">foo2</a></li>
+ </ul>}}</li>]]]
+ [[[item bar <li><a href="bar.html" {{class="#active"}}>bar</a></li>]]]
+ [[[item baz <li><a href="baz.html" {{class="#active"}}>baz</a></li>]]]
+</ul>
+</div>
+
+now in your file foo.html, you use the line
+[[[menu navigation foo]]].
+This line will be replaced by mowyw with:
+
+<div class="menu">
+Navigation:
+<ul>
+ <li><a href="foo.html" class="#active">foo</a>
+ <ul>
+ <li><a href="foo1">foo1</a></li>
+ <li><a href="foo2">foo2</a></li>
+ </ul></li>
+ <li><a href="bar.html" >bar</a></li>
+ <li><a href="baz.html" >baz</a></li>
+</ul>
+</div>
+
+Each menu item looks like this: [[[item label1 some_text]]]. If it is called as
+[[[menu label1]]] it will produce some_text, and all double curly brackets {{ }}
+are simply stripped, but the text between them remains.
+If it is called with a different name, say [[[menu label2]]], the curly brackets
+and the text between them are stripped.
+
+VERBATIM OUTPUT
+
+If your website includes string like [[[ or ]]] etc., you can use the
+verbatim-construct to prevent it from parsing:
+
+[[[verbatim foobarbaz]]]
+Things here inbetween will be printed out exactly as they stand here, you can
+safely write things like
+"in perl6 [...] returns array refs:
+my $a = [2, [4, 5, [8, 9,10]]];"
+note that the ']]]' will not cause any harm.
+[[[endverbatim foobarbaz]]]
+
+the name in the verbatim and in the endverbatim-package have to agree exactly
+and my consist of alphabetic characters and numbers.
+
+
+OMITTING HEADER AND FOOTER
+
+If you include a line like this:
+[[[option no-header]]]
+the header is _not_ prepended as usual.
+You can achieve the following functionality for the footer with the line
+[[[option no-footer]]]
+
+
+LIMITATIONS & BUGS
+ * Currently mowyw is not very flexible in many ways, for example files
+ outside the `include/' directory can't be included.
+
+
+LICENSE:
+ This README file is covered by the GPL (2 or later), however
+ the code examples in this file are public domain, e.g. you may use it
+ however you like.
+ The program mowyw is published under the GPL, for details see the
+ executable
13 TODO
@@ -0,0 +1,13 @@
+TODO:
+ * use configurable prefixes/postfixes 12/2006
+ * Add more magic ;-) 12/2006
+ * more testing 12/2006
+ * print includes pathes in error messages 12/2006
+ * make parser more robust 12/2006
+
+DONE:
+(items formerly on the todo list)
+ * modify parser so that {{ and }} loose their special meaning outside of an
+ [[item]] 12/2006, fixed 12/2006
+ * Implement nested menu items 12/2006, fixed 12/2006
+ * usefull examples 12/2006 fixed 01/2007
1  example/incl_test
@@ -0,0 +1 @@
+[[[include head2]]]
6 example/includes/footer
@@ -0,0 +1,6 @@
+<p id="footer">
+Powered by <a href="http://moritz.faui2k3.org/en/mowyw">mowyw</a> | <a href="#">Imprint</a> | Design by Dimiter Petrov
+</p>
+
+</body>
+</html>
17 example/includes/head2
@@ -0,0 +1,17 @@
+</head>
+
+<body id="home">
+
+<div id="header">
+ <h1>Mowyw Example</h1>
+ <p>Lore Impsum</p>
+</div>
+<div id="nav-page">
+<h2>Quick access</h2>
+<ul>
+<li><a href="#nav-main">Site navigation</a></li>
+<li><a href="#nav-secondary">Recent articles</a></li>
+</ul>
+</div>
+
+<div id="content-main">
8 example/includes/header
@@ -0,0 +1,8 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
+<link rel="stylesheet" type="text/css" media="screen, projection" href="style.css" />
+<link rel="stylesheet" type="text/css" media="print" href="print.css" />
17 example/includes/menu-nav
@@ -0,0 +1,17 @@
+<div id="nav-main">
+<h2>Navigation</h2>
+<ul>
+[[[item home <li><a {{class="active"}} href="index.shtml">Home</a></li>]]]
+[[[item foo <li><a {{class="active"}} href="foo.shtml">foo</a>
+{{
+ <ul>
+ [[[item foo1 <li><a href="foo1.shtml" {{class="active"}}
+ style="margin-left:2em!important">foo1</a></li>]]]
+ [[[item foo2 <li><a href="foo2.shtml" {{class="active"}}
+ style="margin-left:2em!important">foo2</a></li>]]]
+ </ul>
+}}</li>]]]
+[[[item bar <li><a {{class="active"}} href="bar.shtml">bar</a></li>]]]
+</ul>
+</div>
+
9 example/online/.htaccess
@@ -0,0 +1,9 @@
+Options +FollowSymLinks +Includes
+
+AddType 'text/html; charset=ISO-8859-1' shtml
+AddOutputFilter INCLUDES .shtml
+
+DirectoryIndex index.shtml
+
+RewriteEngine On
+#ErrorDocument 404 /404
51 example/online/bar.shtml
@@ -0,0 +1,51 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
+<link rel="stylesheet" type="text/css" media="screen, projection" href="style.css" />
+<link rel="stylesheet" type="text/css" media="print" href="print.css" />
+<title>Mowyw example: page `bar'</title>
+</head>
+
+<body id="home">
+
+<div id="header">
+ <h1>Mowyw Example</h1>
+ <p>Lore Impsum</p>
+</div>
+<div id="nav-page">
+<h2>Quick access</h2>
+<ul>
+<li><a href="#nav-main">Site navigation</a></li>
+<li><a href="#nav-secondary">Recent articles</a></li>
+</ul>
+</div>
+
+<div id="content-main">
+
+
+<h2>Some Foo Bar</h2>
+
+<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed ut dui ac lacus egestas vehicula. Quisque faucibus, risus id consequat porta, orci ligula condimentum mi, ac commodo leo libero eget tortor. Maecenas a ligula in nibh luctus gravida. Praesent vehicula rhoncus tortor. <a href="#">Donec porta rutrum dui.</a> Donec dignissim congue mauris. Sed rhoncus laoreet sem. Nam dui pede, vestibulum convallis, posuere ut, dictum eu, diam. Phasellus nunc. Ut eget ante a ipsum porttitor scelerisque. Quisque auctor elit vitae massa. Vestibulum massa risus, gravida quis, hendrerit sit amet, bibendum sit amet, enim. Fusce nulla. Quisque vulputate metus vitae orci. Pellentesque at arcu. Ut sed neque.</p>
+
+</div>
+
+<div id="nav-main">
+<h2>Navigation</h2>
+<ul>
+ <li><a href="index.shtml">Home</a></li>
+ <li><a href="foo.shtml">foo</a>
+</li>
+ <li><a class="active" href="bar.shtml">bar</a></li>
+</ul>
+</div>
+
+
+<p id="footer">
+Powered by <a href="http://moritz.faui2k3.org/en/mowyw">mowyw</a> | <a href="#">Imprint</a> | Design by Dimiter Petrov
+</p>
+
+</body>
+</html>
58 example/online/foo.shtml
@@ -0,0 +1,58 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
+<link rel="stylesheet" type="text/css" media="screen, projection" href="style.css" />
+<link rel="stylesheet" type="text/css" media="print" href="print.css" />
+<title>Mowyw example: page foo</title>
+</head>
+
+<body id="home">
+
+<div id="header">
+ <h1>Mowyw Example</h1>
+ <p>Lore Impsum</p>
+</div>
+<div id="nav-page">
+<h2>Quick access</h2>
+<ul>
+<li><a href="#nav-main">Site navigation</a></li>
+<li><a href="#nav-secondary">Recent articles</a></li>
+</ul>
+</div>
+
+<div id="content-main">
+
+
+<h2>Bar is the successor of `foo'</h2>
+
+<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed ut dui ac lacus egestas vehicula. Quisque faucibus, risus id consequat porta, orci ligula condimentum mi, ac commodo leo libero eget tortor. Maecenas a ligula in nibh luctus gravida. Praesent vehicula rhoncus tortor. <a href="#">Donec porta rutrum dui.</a> Donec dignissim congue mauris. Sed rhoncus laoreet sem. Nam dui pede, vestibulum convallis, posuere ut, dictum eu, diam. Phasellus nunc. Ut eget ante a ipsum porttitor scelerisque. Quisque auctor elit vitae massa. Vestibulum massa risus, gravida quis, hendrerit sit amet, bibendum sit amet, enim. Fusce nulla. Quisque vulputate metus vitae orci. Pellentesque at arcu. Ut sed neque.</p>
+
+</div>
+
+<div id="nav-main">
+<h2>Navigation</h2>
+<ul>
+ <li><a href="index.shtml">Home</a></li>
+ <li><a class="active" href="foo.shtml">foo</a>
+
+ <ul>
+ <li><a href="foo1.shtml"
+ style="margin-left:2em!important">foo1</a></li>
+ <li><a href="foo2.shtml"
+ style="margin-left:2em!important">foo2</a></li>
+ </ul>
+</li>
+ <li><a href="bar.shtml">bar</a></li>
+</ul>
+</div>
+
+
+<p id="footer">
+Powered by <a href="http://moritz.faui2k3.org/en/mowyw">mowyw</a> | <a href="#">Imprint</a> | Design by Dimiter Petrov
+</p>
+
+</body>
+</html>
58 example/online/foo1.shtml
@@ -0,0 +1,58 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
+<link rel="stylesheet" type="text/css" media="screen, projection" href="style.css" />
+<link rel="stylesheet" type="text/css" media="print" href="print.css" />
+<title>Mowyw example: page foo1</title>
+</head>
+
+<body id="home">
+
+<div id="header">
+ <h1>Mowyw Example</h1>
+ <p>Lore Impsum</p>
+</div>
+<div id="nav-page">
+<h2>Quick access</h2>
+<ul>
+<li><a href="#nav-main">Site navigation</a></li>
+<li><a href="#nav-secondary">Recent articles</a></li>
+</ul>
+</div>
+
+<div id="content-main">
+
+
+<h2>foo1 is a sub item of foo</h2>
+
+<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed ut dui ac lacus egestas vehicula. Quisque faucibus, risus id consequat porta, orci ligula condimentum mi, ac commodo leo libero eget tortor. Maecenas a ligula in nibh luctus gravida. Praesent vehicula rhoncus tortor. <a href="#">Donec porta rutrum dui.</a> Donec dignissim congue mauris. Sed rhoncus laoreet sem. Nam dui pede, vestibulum convallis, posuere ut, dictum eu, diam. Phasellus nunc. Ut eget ante a ipsum porttitor scelerisque. Quisque auctor elit vitae massa. Vestibulum massa risus, gravida quis, hendrerit sit amet, bibendum sit amet, enim. Fusce nulla. Quisque vulputate metus vitae orci. Pellentesque at arcu. Ut sed neque.</p>
+
+</div>
+
+<div id="nav-main">
+<h2>Navigation</h2>
+<ul>
+ <li><a href="index.shtml">Home</a></li>
+ <li><a class="active" href="foo.shtml">foo</a>
+
+ <ul>
+ <li><a href="foo1.shtml" class="active"
+ style="margin-left:2em!important">foo1</a></li>
+ <li><a href="foo2.shtml"
+ style="margin-left:2em!important">foo2</a></li>
+ </ul>
+</li>
+ <li><a href="bar.shtml">bar</a></li>
+</ul>
+</div>
+
+
+<p id="footer">
+Powered by <a href="http://moritz.faui2k3.org/en/mowyw">mowyw</a> | <a href="#">Imprint</a> | Design by Dimiter Petrov
+</p>
+
+</body>
+</html>
58 example/online/foo2.shtml
@@ -0,0 +1,58 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
+<link rel="stylesheet" type="text/css" media="screen, projection" href="style.css" />
+<link rel="stylesheet" type="text/css" media="print" href="print.css" />
+<title>Mowyw example: page foo1</title>
+</head>
+
+<body id="home">
+
+<div id="header">
+ <h1>Mowyw Example</h1>
+ <p>Lore Impsum</p>
+</div>
+<div id="nav-page">
+<h2>Quick access</h2>
+<ul>
+<li><a href="#nav-main">Site navigation</a></li>
+<li><a href="#nav-secondary">Recent articles</a></li>
+</ul>
+</div>
+
+<div id="content-main">
+
+
+<h2>foo2 is another sub item of foo</h2>
+
+<p>And now I'm running out of ideas what to write</p>
+
+</div>
+
+<div id="nav-main">
+<h2>Navigation</h2>
+<ul>
+ <li><a href="index.shtml">Home</a></li>
+ <li><a class="active" href="foo.shtml">foo</a>
+
+ <ul>
+ <li><a href="foo1.shtml"
+ style="margin-left:2em!important">foo1</a></li>
+ <li><a href="foo2.shtml" class="active"
+ style="margin-left:2em!important">foo2</a></li>
+ </ul>
+</li>
+ <li><a href="bar.shtml">bar</a></li>
+</ul>
+</div>
+
+
+<p id="footer">
+Powered by <a href="http://moritz.faui2k3.org/en/mowyw">mowyw</a> | <a href="#">Imprint</a> | Design by Dimiter Petrov
+</p>
+
+</body>
+</html>
BIN  example/online/images/arrow.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  example/online/images/bg.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  example/online/images/document.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
87 example/online/index.shtml
@@ -0,0 +1,87 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
+<head>
+<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" />
+<link rel="stylesheet" type="text/css" media="screen, projection" href="style.css" />
+<link rel="stylesheet" type="text/css" media="print" href="print.css" />
+<title>Mowyw example</title>
+</head>
+
+<body id="home">
+
+<div id="header">
+ <h1>Mowyw Example</h1>
+ <p>Lore Impsum</p>
+</div>
+<div id="nav-page">
+<h2>Quick access</h2>
+<ul>
+<li><a href="#nav-main">Site navigation</a></li>
+<li><a href="#nav-secondary">Recent articles</a></li>
+</ul>
+</div>
+
+<div id="content-main">
+
+
+<h2>A Word on the Design</h2>
+
+<p>This design is "stolen" from Dimiter Petrov, it is published on <a
+href="http://www.oswd.org/">oswd.org</a> under the name "Ordered
+Boxes".</p>
+
+<p>As far as I understand it is public domain, but he kindly asks anybody
+using this design to keep his name in the footer line.</p>
+
+<h2>Lore Ipsum</h2>
+
+<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed ut dui ac
+lacus egestas vehicula. Quisque faucibus, risus id consequat porta, orci
+ligula condimentum mi, ac commodo leo libero eget tortor. Maecenas a ligula in
+nibh luctus gravida. Praesent vehicula rhoncus tortor. <a href="#">Donec porta
+rutrum dui.</a> Donec dignissim congue mauris. Sed rhoncus laoreet sem. Nam
+dui pede, vestibulum convallis, posuere ut, dictum eu, diam. Phasellus nunc.
+Ut eget ante a ipsum porttitor scelerisque. Quisque auctor elit vitae massa.
+Vestibulum massa risus, gravida quis, hendrerit sit amet, bibendum sit amet,
+enim. Fusce nulla. Quisque vulputate metus vitae orci. Pellentesque
+at arcu. Ut sed neque.</p>
+
+<h2>Some Tests</h2>
+
+<p>These tests only tests some properties of the parser, you can safly ignore
+and delete them.</p>
+
+<h3>Parse test</h3>
+<p>Double braces should be ignored outside of an item: }} foo bar {{ {{.</p>
+
+<h3>Option parsing</h3>
+<p>Option items should be stripped, so the there should be no "option foo"
+output on the next line.</p>
+
+
+<h3>Verbose tests</h3>
+<p>Text between [[[verbatim $marker]]] and [[[endverbatim
+$marker]]] should be treated as plain text, e.g. tags inbetween should be
+ignored: [[[include foo]]].</p>
+
+</div>
+
+<div id="nav-main">
+<h2>Navigation</h2>
+<ul>
+ <li><a class="active" href="index.shtml">Home</a></li>
+ <li><a href="foo.shtml">foo</a>
+</li>
+ <li><a href="bar.shtml">bar</a></li>
+</ul>
+</div>
+
+
+<p id="footer">
+Powered by <a href="http://moritz.faui2k3.org/en/mowyw">mowyw</a> | <a href="#">Imprint</a> | Design by Dimiter Petrov
+</p>
+
+</body>
+</html>
3  example/online/no-header-footer.shtml
@@ -0,0 +1,3 @@
+This file should not have a header or footer attached to it
+
+
17 example/online/print.css
@@ -0,0 +1,17 @@
+* {
+ float: none;
+ border: none;
+ background: #fff;
+}
+
+h2 {
+ font-weight: normal;
+}
+
+body {
+ font: medium/1.8em "Trebuchet MS", Verdana, Helvetica, sans-serif;
+}
+
+#nav-page, #nav-main, #nav-secondary {
+ display: none;
+}
149 example/online/style.css
@@ -0,0 +1,149 @@
+body {
+ font: small/1.8em "Trebuchet MS", Verdana, Helvetica, sans-serif;
+ color: #222;
+ margin: 0;
+ padding: 0 1em;
+ background: #5B99D7 url(images/bg.png);
+}
+
+h1 {
+ font-size: 3em;
+ font-weight: normal;
+ line-height: 1.3em;
+}
+
+h2 {
+ font-size: large;
+ font-weight: normal;
+}
+
+h3 {
+ font-size: medium;
+ font-weight: normal;
+}
+
+a {
+ color: #2a65ad;
+ color: #2A65AC;
+ font-weight: bold;
+ text-decoration: none;
+}
+
+a:visited {
+ color: #3A7DCF;
+}
+
+a:hover {
+ color: #000;
+ border-bottom: 1px solid;
+}
+
+img {
+ border: 0;
+}
+
+input {
+ border: 1px solid #bbb;
+}
+input:focus {
+ border: 1px solid #C6DDF1;
+}
+
+.hide {
+ position: absolute;
+ left: -9000px;
+ display: none;
+}
+
+#header {
+ margin: 0 0 1em 0;
+ padding: 1em 3em;
+ background: #fff;
+ border: solid;
+ border-width: 0 2px 2px 1px;
+ border-color: #ccc #777 #333 #ddd;
+}
+
+#header p {
+ font-size: large;
+ font-weight: light;
+}
+
+#nav-page {
+ position: absolute;
+ left: -5000px;
+}
+
+#content-main {
+ float: right;
+ width: 60%;
+ padding: 1.5em 2em;
+ margin: 0 0 1em;
+/* max-width: 70em; */
+}
+
+#nav-main {
+ float: left;
+ width: 25%;
+ padding: 1.5em;
+ letter-spacing: 0.1em;
+}
+.active {
+ color: #000 !important;
+ background: #98BFE6 url(images/arrow.gif) 0.2em no-repeat !important;
+}
+ #nav-main ul {
+ padding: 0;
+ margin: 0;
+ list-style: none;
+ }
+ #nav-main li {
+ margin: 2px 0;
+ }
+ #nav-main li a {
+ display: block;
+ height: 100%;
+ border: none;
+ padding: 0 0 0 20px;
+ background: url(images/arrow.gif) 0.2em no-repeat;
+ }
+ #nav-main li a:hover {
+ background-color: #C6DDF1;
+ }
+
+#nav-secondary {
+ float: left;
+ width: 25%;
+ margin-top: 1em;
+ padding: 1.5em;
+}
+ #nav-secondary ul {
+ padding: 0;
+ margin: 0;
+ list-style: none;
+ }
+ #nav-secondary li a {
+ padding-left: 20px;
+ border: none;
+ background: url(images/document.gif) 0.2em no-repeat;
+ }
+
+#footer {
+ clear: both;
+ position: relative;
+ font-size: 0.9em;
+ text-align: center;
+ margin: 1em 0 0 0;
+ padding: 1em 1em 1.5em;
+ background: #fff;
+ border: solid;
+ border-width: 1px 2px 0 1px;
+ border-color: #ccc #777 #333 #ddd;
+}
+
+#content-main, #nav-main, #nav-secondary{
+ background: #fff;
+ border: solid;
+ border-width: 1px 2px 2px 1px;
+ border-color: #ccc #777 #333 #ddd;
+}
9 example/source/.htaccess
@@ -0,0 +1,9 @@
+Options +FollowSymLinks +Includes
+
+AddType 'text/html; charset=ISO-8859-1' shtml
+AddOutputFilter INCLUDES .shtml
+
+DirectoryIndex index.shtml
+
+RewriteEngine On
+#ErrorDocument 404 /404
10 example/source/bar.shtml
@@ -0,0 +1,10 @@
+<title>Mowyw example: page `bar'</title>
+[[[include head2]]]
+
+<h2>Some Foo Bar</h2>
+
+<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed ut dui ac lacus egestas vehicula. Quisque faucibus, risus id consequat porta, orci ligula condimentum mi, ac commodo leo libero eget tortor. Maecenas a ligula in nibh luctus gravida. Praesent vehicula rhoncus tortor. <a href="#">Donec porta rutrum dui.</a> Donec dignissim congue mauris. Sed rhoncus laoreet sem. Nam dui pede, vestibulum convallis, posuere ut, dictum eu, diam. Phasellus nunc. Ut eget ante a ipsum porttitor scelerisque. Quisque auctor elit vitae massa. Vestibulum massa risus, gravida quis, hendrerit sit amet, bibendum sit amet, enim. Fusce nulla. Quisque vulputate metus vitae orci. Pellentesque at arcu. Ut sed neque.</p>
+
+</div>
+
+[[[menu nav bar]]]
10 example/source/foo.shtml
@@ -0,0 +1,10 @@
+<title>Mowyw example: page foo</title>
+[[[include head2]]]
+
+<h2>Bar is the successor of `foo'</h2>
+
+<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed ut dui ac lacus egestas vehicula. Quisque faucibus, risus id consequat porta, orci ligula condimentum mi, ac commodo leo libero eget tortor. Maecenas a ligula in nibh luctus gravida. Praesent vehicula rhoncus tortor. <a href="#">Donec porta rutrum dui.</a> Donec dignissim congue mauris. Sed rhoncus laoreet sem. Nam dui pede, vestibulum convallis, posuere ut, dictum eu, diam. Phasellus nunc. Ut eget ante a ipsum porttitor scelerisque. Quisque auctor elit vitae massa. Vestibulum massa risus, gravida quis, hendrerit sit amet, bibendum sit amet, enim. Fusce nulla. Quisque vulputate metus vitae orci. Pellentesque at arcu. Ut sed neque.</p>
+
+</div>
+
+[[[menu nav foo]]]
10 example/source/foo1.shtml
@@ -0,0 +1,10 @@
+<title>Mowyw example: page foo1</title>
+[[[include head2]]]
+
+<h2>foo1 is a sub item of foo</h2>
+
+<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed ut dui ac lacus egestas vehicula. Quisque faucibus, risus id consequat porta, orci ligula condimentum mi, ac commodo leo libero eget tortor. Maecenas a ligula in nibh luctus gravida. Praesent vehicula rhoncus tortor. <a href="#">Donec porta rutrum dui.</a> Donec dignissim congue mauris. Sed rhoncus laoreet sem. Nam dui pede, vestibulum convallis, posuere ut, dictum eu, diam. Phasellus nunc. Ut eget ante a ipsum porttitor scelerisque. Quisque auctor elit vitae massa. Vestibulum massa risus, gravida quis, hendrerit sit amet, bibendum sit amet, enim. Fusce nulla. Quisque vulputate metus vitae orci. Pellentesque at arcu. Ut sed neque.</p>
+
+</div>
+
+[[[menu nav foo foo1]]]
10 example/source/foo2.shtml
@@ -0,0 +1,10 @@
+<title>Mowyw example: page foo1</title>
+[[[include head2]]]
+
+<h2>foo2 is another sub item of foo</h2>
+
+<p>And now I'm running out of ideas what to write</p>
+
+</div>
+
+[[[menu nav foo foo2]]]
BIN  example/source/images/arrow.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  example/source/images/bg.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
BIN  example/source/images/document.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
46 example/source/index.shtml
@@ -0,0 +1,46 @@
+<title>Mowyw example</title>
+[[[include head2]]]
+
+<h2>A Word on the Design</h2>
+
+<p>This design is "stolen" from Dimiter Petrov, it is published on <a
+href="http://www.oswd.org/">oswd.org</a> under the name "Ordered
+Boxes".</p>
+
+<p>As far as I understand it is public domain, but he kindly asks anybody
+using this design to keep his name in the footer line.</p>
+
+<h2>Lore Ipsum</h2>
+
+<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Sed ut dui ac
+lacus egestas vehicula. Quisque faucibus, risus id consequat porta, orci
+ligula condimentum mi, ac commodo leo libero eget tortor. Maecenas a ligula in
+nibh luctus gravida. Praesent vehicula rhoncus tortor. <a href="#">Donec porta
+rutrum dui.</a> Donec dignissim congue mauris. Sed rhoncus laoreet sem. Nam
+dui pede, vestibulum convallis, posuere ut, dictum eu, diam. Phasellus nunc.
+Ut eget ante a ipsum porttitor scelerisque. Quisque auctor elit vitae massa.
+Vestibulum massa risus, gravida quis, hendrerit sit amet, bibendum sit amet,
+enim. Fusce nulla. Quisque vulputate metus vitae orci. Pellentesque
+at arcu. Ut sed neque.</p>
+
+<h2>Some Tests</h2>
+
+<p>These tests only tests some properties of the parser, you can safly ignore
+and delete them.</p>
+
+<h3>Parse test</h3>
+<p>Double braces should be ignored outside of an item: }} foo bar {{ {{.</p>
+
+<h3>Option parsing</h3>
+<p>Option items should be stripped, so the there should be no "option foo"
+output on the next line.</p>
+[[[option foo]]]
+
+<h3>Verbose tests</h3>
+<p>[[[verbatim foobar]]]Text between [[[verbatim $marker]]] and [[[endverbatim
+$marker]]] should be treated as plain text, e.g. tags inbetween should be
+ignored: [[[include foo]]][[[endverbatim foobar]]].</p>
+
+</div>
+
+[[[menu nav home]]]
3  example/source/no-header-footer.shtml
@@ -0,0 +1,3 @@
+This file should not have a header or footer attached to it
+[[[option no-header]]]
+[[[option no-footer]]]
17 example/source/print.css
@@ -0,0 +1,17 @@
+* {
+ float: none;
+ border: none;
+ background: #fff;
+}
+
+h2 {
+ font-weight: normal;
+}
+
+body {
+ font: medium/1.8em "Trebuchet MS", Verdana, Helvetica, sans-serif;
+}
+
+#nav-page, #nav-main, #nav-secondary {
+ display: none;
+}
149 example/source/style.css
@@ -0,0 +1,149 @@
+body {
+ font: small/1.8em "Trebuchet MS", Verdana, Helvetica, sans-serif;
+ color: #222;
+ margin: 0;
+ padding: 0 1em;
+ background: #5B99D7 url(images/bg.png);
+}
+
+h1 {
+ font-size: 3em;
+ font-weight: normal;
+ line-height: 1.3em;
+}
+
+h2 {
+ font-size: large;
+ font-weight: normal;
+}
+
+h3 {
+ font-size: medium;
+ font-weight: normal;
+}
+
+a {
+ color: #2a65ad;
+ color: #2A65AC;
+ font-weight: bold;
+ text-decoration: none;
+}
+
+a:visited {
+ color: #3A7DCF;
+}
+
+a:hover {
+ color: #000;
+ border-bottom: 1px solid;
+}
+
+img {
+ border: 0;
+}
+
+input {
+ border: 1px solid #bbb;
+}
+input:focus {
+ border: 1px solid #C6DDF1;
+}
+
+.hide {
+ position: absolute;
+ left: -9000px;
+ display: none;
+}
+
+#header {
+ margin: 0 0 1em 0;
+ padding: 1em 3em;
+ background: #fff;
+ border: solid;
+ border-width: 0 2px 2px 1px;
+ border-color: #ccc #777 #333 #ddd;
+}
+
+#header p {
+ font-size: large;
+ font-weight: light;
+}
+
+#nav-page {
+ position: absolute;
+ left: -5000px;
+}
+
+#content-main {
+ float: right;
+ width: 60%;
+ padding: 1.5em 2em;
+ margin: 0 0 1em;
+/* max-width: 70em; */
+}
+
+#nav-main {
+ float: left;
+ width: 25%;
+ padding: 1.5em;
+ letter-spacing: 0.1em;
+}
+.active {
+ color: #000 !important;
+ background: #98BFE6 url(images/arrow.gif) 0.2em no-repeat !important;
+}
+ #nav-main ul {
+ padding: 0;
+ margin: 0;
+ list-style: none;
+ }
+ #nav-main li {
+ margin: 2px 0;
+ }
+ #nav-main li a {
+ display: block;
+ height: 100%;
+ border: none;
+ padding: 0 0 0 20px;
+ background: url(images/arrow.gif) 0.2em no-repeat;
+ }
+ #nav-main li a:hover {
+ background-color: #C6DDF1;
+ }
+
+#nav-secondary {
+ float: left;
+ width: 25%;
+ margin-top: 1em;
+ padding: 1.5em;
+}
+ #nav-secondary ul {
+ padding: 0;
+ margin: 0;
+ list-style: none;
+ }
+ #nav-secondary li a {
+ padding-left: 20px;
+ border: none;
+ background: url(images/document.gif) 0.2em no-repeat;
+ }
+
+#footer {
+ clear: both;
+ position: relative;
+ font-size: 0.9em;
+ text-align: center;
+ margin: 1em 0 0 0;
+ padding: 1em 1em 1.5em;
+ background: #fff;
+ border: solid;
+ border-width: 1px 2px 0 1px;
+ border-color: #ccc #777 #333 #ddd;
+}
+
+#content-main, #nav-main, #nav-secondary{
+ background: #fff;
+ border: solid;
+ border-width: 1px 2px 2px 1px;
+ border-color: #ccc #777 #333 #ddd;
+}
20 lexer_test.pl
@@ -0,0 +1,20 @@
+#!/usr/bin/perl
+# test Mowyw::Lexer
+use warnings;
+use strict;
+use Mowyw::Lexer qw(lex);
+
+
+my @tokens = (
+ ['Int', qr/(?:-|\+)?\d+/],
+ ['Op', qr/\+|\*|-|\//],
+ ['Brace_Open', qr/\(/],
+ ['Brace_Close', qr/\)/],
+ ['Whitespace', qr/\s/, sub { return undef; }],
+ );
+my $text = "12 + foo (3 * (4 + -1))BAR";
+my @pt = lex($text, \@tokens);
+foreach (@pt){
+ my ($name, $text) = @$_;
+ print "Found Token $name: $text\n";
+}
412 mowyw
@@ -0,0 +1,412 @@
+#!/usr/bin/perl
+# mowyw - mowyw writes your websites - Copyright (C) 2006 Moritz Lenz
+# For documentation please see the README file
+# <moritz@faui2k3.org>
+# Snail Mail address:
+# Moritz Lenz
+# Killingerstr. 92
+# 91056 Erlangen
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program 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 General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+use warnings;
+use strict;
+use FindBin;
+use lib "$FindBin::Bin";
+use File::Copy;
+use File::Temp qw(tempfile);
+use File::Compare;
+use Mowyw::Lexer qw(lex);
+use Carp;
+use Storable qw(dclone);
+
+use Data::Dumper;
+
+sub process_file($);
+sub process_dir($);
+sub process_menu_tree;
+sub read_and_lex_file($);
+
+my $includes_prefix = "includes/";
+my $source_prefix = "source/";
+my $dest_prefix = "online/";
+my $menu_prefix = $includes_prefix . "menu-";
+my $postfix = "";
+
+my @todo = qw(source);
+my $header_content = undef;
+my $footer_content = undef;
+
+my $internal_error_message = "Please contact the Author at moritz\@faui2k3.org providing\nan example hwo to reproduce the error, including the complete error message";
+
+my @input_tokens = (
+ [ 'TAG_START', qr/\[\[\[\s*/],
+ [ 'KEYWORD', qr/(?:include|menu|option|item|endverbatim|verbatim)/],
+ [ 'TAG_END', qr/\s*\]\]\]/],
+ [ 'BRACES_START', qr/{{/],
+ [ 'BRACES_END', qr/}}/],
+ );
+
+main();
+#my %metadata = (ITEMS => [],
+# FILES => [],
+# CURRENT_ITEM => undef,
+# OPTIONS => {},
+# );
+#my $str = parse_file("includes/head2", \%metadata);
+#print $str;
+
+
+sub main {
+ while (my $fn = pop @todo){
+ $fn .= '/' unless ($fn =~ m#/$#);
+ opendir DIR, $fn;
+ IW: while (my $f = readdir DIR){
+ # ignore symbolic links and non-Readable files:
+ next IW if (-l $f);
+ # if we consider . and .., we loop infinetly.
+ # and while we are at ignoring, we can ignore a few
+ # other things as well ;-)
+ if ($f =~ m#^\.\.?$#
+ or $f =~ m#^\.svn$#
+ or $f =~ m#(?:~|\.swp)$#){
+# print STDERR "Ignoring '$f'\n";
+ next;
+ }
+ $f = $fn . $f;
+ if (-d $f){
+ push @todo, $f;
+ process_dir($f);
+ } else {
+ process_file($f);
+ }
+ }
+ closedir DIR;
+ }
+}
+
+sub process_file($){
+ my $fn = shift;
+ my $new_fn = $fn;
+ $new_fn =~ s#^$source_prefix#$dest_prefix#;
+ if ($fn =~ m#\..?htm# && $fn !~ m#\.swp$#){
+ print STDERR "Processing File '$fn'...";
+
+
+ my %metadata = (ITEMS => [],
+ FILES => [],
+ CURRENT_ITEM => undef,
+ OPTIONS => {},
+ );
+ my $str = parse_file($fn, \%metadata);
+# print Data::Dumper->Dump([\%metadata]);
+ my $header = "";
+ my $footer = "";
+# warn $str;
+ unless (exists $metadata{OPTIONS}->{'no-header'}){
+ $header = parse_file($includes_prefix . "header" . $postfix, \%metadata);
+ }
+ unless (exists $metadata{OPTIONS}->{'no-footer'}){
+ $footer = parse_file($includes_prefix . "footer" . $postfix, \%metadata);
+ }
+ my ($tmp_fh, $tmp_name) = tempfile();
+ print $tmp_fh $header;
+ print $tmp_fh $str;
+ print $tmp_fh $footer;
+ close $tmp_fh;
+ if (compare($new_fn, $tmp_name) == 0){
+ print " not changed\n";
+ } else {
+ copy($tmp_name, $new_fn);
+ print " done\n";
+ }
+ } else {
+ if (compare($fn, $new_fn) == 0){
+ # do nothing
+ } else {
+ copy($fn, $new_fn);
+ print "Updated file $new_fn (not processed)\n";
+ }
+ }
+}
+
+sub parse_file {
+ my $fn = shift;
+ my $meta= shift;
+ my @tokens = read_and_lex_file($fn);
+# print Data::Dumper->Dump(\@tokens);
+ return parse_tokens(\@tokens, $meta);
+}
+
+
+sub read_and_lex_file($) {
+ my $fn = shift;
+ my $meta = shift;
+
+ open(my $in_file, $fn) or die "Can't read '$fn': $!";
+ my $text = join "", <$in_file>;
+ close $in_file;
+ my @tokens = lex($text, \@input_tokens);
+# print Data::Dumper->Dump(\@tokens);
+
+ return @tokens;
+}
+
+sub parse_tokens {
+ my $tokens = shift;
+ my $meta = shift;
+ my $str = "";
+ if ($meta->{INSIDE_ITEM}){
+ $str .= p_text($tokens);
+ } else {
+ $str .= p_text($tokens, {BRACES_START => 1, BRACES_END => 1});
+ }
+ while(@$tokens
+ and $tokens->[0]->[0] ne "TAG_END"
+ and $tokens->[0]->[0] ne "BRACES_END"){
+# print scalar @$tokens;
+# print " tokens left\n";
+# warn $str;
+
+ if ($tokens->[0]->[0] eq "TAG_START"){
+ p_expect($tokens, "TAG_START", $meta);
+ my $key = p_expect($tokens, 'KEYWORD', $meta);
+ if ($key eq "include") {
+ $str .= p_include($tokens, $meta);
+ } elsif ($key eq "menu"){
+ $str .= p_menu($tokens, $meta);
+ } elsif ($key eq "item") {
+ $str .= p_item($tokens, $meta);
+ } elsif ($key eq "option"){
+ p_option($tokens, $meta);
+ } elsif ($key eq "verbatim"){
+ $str .= p_verbatim($tokens, $meta);
+ } elsif ($key eq "endverbatim"){
+ parse_error("Unexpected tag 'endverbatim' without prior 'verbatim'");
+ }
+ } elsif ($tokens->[0]->[0] eq "BRACES_START") {
+# print "Working on braces\n";
+ $str .= p_braces($tokens, $meta);
+ } else {
+ print "Don't know what to do with token $tokens->[0]->[0]\n";
+ }
+ if ($meta->{INSIDE_ITEM}){
+ $str .= p_text($tokens);
+ } else {
+ $str .= p_text($tokens, {BRACES_START => 1, BRACES_END => 1});
+ }
+
+ }
+ return $str;
+}
+
+# parse sub: anything is treated as normal text that does not start or end a
+# command
+# the second (optional) arg contains a hash of additional tokens that are
+# treated as plain text
+sub p_text {
+ my $tokens = shift;
+ my %a;
+ %a = %{$_[0]} if ($_[0]);
+ my $str = "";
+ my %allowed_tokens = (
+ KEYWORD => 1,
+ UNMATCHED => 1,
+ );
+
+ while ( $tokens
+ and $tokens->[0]
+ and $tokens->[0]->[0]
+ and ($allowed_tokens{$tokens->[0]->[0]}
+ or $a{$tokens->[0]->[0]})){
+ $str .= $tokens->[0]->[1];
+ shift @$tokens;
+ }
+ return $str;
+}
+
+# parse sub: parse an include statement.
+# note that TAG_START and the keyword "include" are already stripped
+sub p_include {
+ my $tokens = shift;
+ my $meta = shift;
+ # normally we'd expect an UNMATCHED token, but the user might choose
+ # a keyword as well as file name
+ if ($tokens->[0]->[0] eq "UNMATCHED" or $tokens->[0]->[0] eq "KEYWORD"){
+ my $fn = strip_ws($tokens->[0]->[1]);
+ $fn = $includes_prefix . $fn . $postfix;
+ shift @$tokens;
+ p_expect($tokens, "TAG_END", $meta);
+ # include file
+ my $m = dclone($meta);
+ push @{$m->{FILES}}, $fn;
+ return parse_file($fn, $m);
+ } else {
+ cloak("Expected: File name. Got: $tokens->[0]->[1]");
+ }
+}
+
+# parse sub: parse a 'menu' statement.
+# note that TAG_START and the keyword "menu" are already stripped
+sub p_menu {
+ my $tokens = shift;
+ my $meta = shift;
+ my $key = strip_ws(p_expect($tokens, "UNMATCHED", $meta));
+# warn "menu string: $key";
+ my @words = split /\s+/, $key;
+ p_expect($tokens, "TAG_END", $meta);
+ my $menu_fn = shift @words;
+ $menu_fn = $menu_prefix . $menu_fn . $postfix;
+ my $m = dclone($meta);
+ push @{$m->{ITEMS}}, @words;
+ push @{$m->{FILES}}, $menu_fn;
+ return parse_file($menu_fn, $m);
+}
+
+# parse sub: parse an 'option' statement
+sub p_option {
+ my $tokens = shift;
+ my $meta = shift;
+ my $key = strip_ws(p_expect($tokens, "UNMATCHED", $meta));
+ my @words = split /\s+/, $key;
+ my $option_key = shift @words;
+ my $option_val = join " ", @words;
+ $meta->{OPTIONS}->{$option_key} = $option_val;
+ p_expect($tokens, "TAG_END", $meta);
+}
+
+#parse sub: parse an "item" statement
+sub p_item {
+ my $tokens = shift;
+ my $meta = shift;
+ my $content = p_expect($tokens, "UNMATCHED", $meta);
+ $content =~ s/^\s+//;
+ $content =~ m/^(\S+)/;
+ my $key = $1;
+ $content =~ s/^\S+//;
+
+ my $m = dclone($meta);
+# print Data::Dumper->Dump([$m]);
+ if ($meta->{ITEMS}->[0] and $meta->{ITEMS}->[0] eq $key){
+# print "Found matching item\n";
+ shift @{$m->{ITEMS}};
+ $m->{CURRENT_ITEM} = $key;
+
+ } else {
+# print "Found non-matching item\n";
+ $m->{ITEMS} = [];
+ $m->{CURRENT_ITEM} = undef;
+ }
+ $m->{INSIDE_ITEM} = 1;
+ my $str = $content . parse_tokens($tokens, $m);
+ p_expect($tokens, "TAG_END", $meta);
+ return $str;
+
+}
+
+sub p_verbatim {
+ my $tokens = shift;
+ my $meta = shift;
+ my $str = "";
+ my $key = "";
+ if ($tokens->[0]->[0] eq "keyword"){
+ $key = p_expect($tokens, "KEYWORD", $meta);
+ } else {
+ $key = p_expect($tokens, "UNMATCHED", $meta);
+ }
+ p_expect($tokens, "TAG_END", $meta);
+ while (@$tokens){
+ if ($tokens->[0]->[0] eq "TAG_START"
+ and $tokens->[1]->[0] eq "KEYWORD"
+ and $tokens->[1]->[1] eq "endverbatim"
+ and $tokens->[2]->[1] eq $key
+ and $tokens->[3]->[0] eq "TAG_END"){
+ # found end of verbatim section
+ p_expect($tokens, "TAG_START", $meta);
+ p_expect($tokens, "KEYWORD", $meta);
+ shift @$tokens;
+ p_expect($tokens, "TAG_END", $meta);
+ return $str;
+ } else {
+ $str .= $tokens->[0]->[1];
+ shift @$tokens;
+ }
+ }
+ die "[[[verbatim $key]]] opened but not closed until end of file\n";
+}
+
+sub p_braces {
+ my $tokens = shift;
+ my $meta = shift;
+ my $str = "";
+ p_expect($tokens,"BRACES_START", $meta);
+ if ($meta->{CURRENT_ITEM}){
+# print "using text inside braces\n";
+ $str .= parse_tokens($tokens, $meta);
+ } else {
+ # discard the text between opening {{ and closing }} braces
+# print "discarding text inside braces\n";
+ parse_tokens($tokens, $meta);
+ }
+ p_expect($tokens, "BRACES_END", $meta);
+ return $str;
+}
+
+# parse sub: expect a specific token, return its content or die if the
+# expectation was not met.
+sub p_expect {
+ my $tokens = shift;
+ my $expect = shift;
+ my $meta = shift;
+# print Data::Dumper->Dump([$tokens]);
+ confess("Expected $expect, got nothing\n") unless (@$tokens);
+ confess("\$tokens not a array ref - this is most likely a programming error\n$internal_error_message") unless(ref($tokens) eq "ARRAY");
+ if ($tokens->[0]->[0] eq $expect){
+ my $e_val = shift;
+ if (not defined($e_val) or $e_val eq $tokens->[0]->[1]){
+ my $val = $tokens->[0]->[1];
+ shift @$tokens;
+ return $val;
+ }
+ }
+ confess("Expected token $expect, got $tokens->[0]->[0]\n");
+}
+
+
+sub process_dir($) {
+ my $fn = shift;
+ print STDERR "Processing Directory '$fn'\n";
+ my $new_fn = $fn;
+ $new_fn =~ s#^$source_prefix#$dest_prefix/#;
+ mkdir $new_fn;
+}
+
+# strip leading and trailing whitespaces from a string
+sub strip_ws($) {
+ my $s = shift;
+ $s =~ s/^\s+//g;
+ $s =~ s/\s+$//g;
+ return $s;
+}
+
+sub parse_error {
+ my $message = shift;
+ my $fn = shift;
+ print STDERR "Parse error in file '$fn': $message\n";
+ while ($fn = shift){
+ print STDERR "\t...included from file '$fn'\n";
+ }
+ exit 1;
+}
Please sign in to comment.
Something went wrong with that request. Please try again.