[valadoc] Parser: Add support for lists



commit c473f549d04477ea4515e05b8f219f5ada354002
Author: Didier 'Ptitjes <ptitjes at free dot fr>
Date:   Sat Oct 31 03:31:43 2009 +0100

    Parser: Add support for lists

 icons/devhelpstyle.css                             |    4 +-
 icons/style.css                                    |    4 +-
 icons/wikistyle.css                                |    5 +
 src/libvaladoc/content/list.vala                   |   23 +++-
 src/libvaladoc/content/listitem.vala               |   30 ++---
 .../documentation/documentationparser.vala         |  137 +++++++++++++++----
 src/libvaladoc/documentation/wikiscanner.vala      |    9 --
 src/libvaladoc/html/htmlmarkupwriter.vala          |    1 +
 src/libvaladoc/html/htmlrenderer.vala              |   41 ++++++
 src/libvaladoc/parser/optionalrule.vala            |    2 +-
 src/libvaladoc/parser/rule.vala                    |   12 ++
 src/libvaladoc/parser/sequencerule.vala            |    2 +
 src/libvaladoc/parser/tokentype.vala               |    4 -
 13 files changed, 209 insertions(+), 65 deletions(-)
---
diff --git a/icons/devhelpstyle.css b/icons/devhelpstyle.css
index e3271c5..9e40478 100644
--- a/icons/devhelpstyle.css
+++ b/icons/devhelpstyle.css
@@ -467,7 +467,9 @@ a.navi_link:hover, a.external_link:hover {
 	text-decoration: underline;
 }
 
-
+ul.no_bullet > li {
+	list-style-type: none;
+}
 
 
 .main_see_list {
diff --git a/icons/style.css b/icons/style.css
index eb4d280..3124d44 100644
--- a/icons/style.css
+++ b/icons/style.css
@@ -481,7 +481,9 @@ a.navi_link:hover, a.external_link:hover {
 	text-decoration: underline;
 }
 
-
+ul.no_bullet > li {
+	list-style-type: none;
+}
 
 
 .main_see_list {
diff --git a/icons/wikistyle.css b/icons/wikistyle.css
index 5f7f0eb..ab128be 100644
--- a/icons/wikistyle.css
+++ b/icons/wikistyle.css
@@ -479,6 +479,11 @@ a.navi_link:hover, a.external_link:hover {
 	text-decoration: underline;
 }
 
+ul.no_bullet > li {
+	list-style-type: none;
+}
+
+
 .main_see_list {
 }
 
diff --git a/src/libvaladoc/content/list.vala b/src/libvaladoc/content/list.vala
index 882715a..4170a43 100755
--- a/src/libvaladoc/content/list.vala
+++ b/src/libvaladoc/content/list.vala
@@ -24,18 +24,30 @@ using Gee;
 
 
 public class Valadoc.Content.List : ContentElement, Block {
+	public enum Bullet {
+		NONE,
+		UNORDERED,
+		ORDERED,
+		ORDERED_NUMBER,
+		ORDERED_LOWER_CASE_ALPHA,
+		ORDERED_UPPER_CASE_ALPHA,
+		ORDERED_LOWER_CASE_ROMAN,
+		ORDERED_UPPER_CASE_ROMAN
+	}
+
+	public Bullet bullet { get; set; }
+	// TODO add initial value (either a number or some letters)
 	public Gee.List<ListItem> items { get { return _items; } }
 
 	private Gee.List<ListItem> _items;
 
 	internal List () {
 		base ();
+		_bullet = Bullet.NONE;
 		_items = new ArrayList<ListItem> ();
 	}
 
 	public override void check (Api.Tree api_root, Api.Node? container, ErrorReporter reporter) {
-		// Check the list consistency in terms of successive item levels ?
-
 		// Check individual list items
 		foreach (ListItem element in _items) {
 			element.check (api_root, container, reporter);
@@ -45,5 +57,10 @@ public class Valadoc.Content.List : ContentElement, Block {
 	public override void accept (ContentVisitor visitor) {
 		visitor.visit_list (this);
 	}
-}
 
+	public override void accept_children (ContentVisitor visitor) {
+		foreach (ListItem element in _items) {
+			element.accept (visitor);
+		}
+	}
+}
diff --git a/src/libvaladoc/content/listitem.vala b/src/libvaladoc/content/listitem.vala
index 31f7db5..8a2c6f9 100755
--- a/src/libvaladoc/content/listitem.vala
+++ b/src/libvaladoc/content/listitem.vala
@@ -24,34 +24,30 @@ using Gee;
 
 
 public class Valadoc.Content.ListItem : InlineContent {
-	public enum Bullet {
-		NONE,
-		UNORDERED,
-		ORDERED,
-		ORDERED_LATIN,
-		ORDERED_CAPITAL,
-		ORDERED_NUMBER,
-		ORDERED_LOWER_CASE
-	}
-
-	public Bullet bullet { get; set; }
-	public int level { get; set; }
+	public List? sub_list { get; set; }
 
 	internal ListItem () {
 		base ();
-		_bullet = Bullet.UNORDERED;
-		_level = 0;
 	}
 
 	public override void check (Api.Tree api_root, Api.Node? container, ErrorReporter reporter) {
-		// TODO report error if level == 0 ?
-
 		// Check inline content
 		base.check (api_root, container, reporter);
+
+		if (sub_list != null) {
+			sub_list.check (api_root, container, reporter);
+		}
 	}
 
 	public override void accept (ContentVisitor visitor) {
 		visitor.visit_list_item (this);
 	}
-}
 
+	public override void accept_children (ContentVisitor visitor) {
+		base.accept_children (visitor);
+
+		if (sub_list != null) {
+			sub_list.accept (visitor);
+		}
+	}
+}
diff --git a/src/libvaladoc/documentation/documentationparser.vala b/src/libvaladoc/documentation/documentationparser.vala
index 273b9d6..28e0fcc 100644
--- a/src/libvaladoc/documentation/documentationparser.vala
+++ b/src/libvaladoc/documentation/documentationparser.vala
@@ -115,9 +115,9 @@ public class Valadoc.DocumentationParser : Object, ResourceLocator {
 		_stack.add (element);
 	}
 
-	private Object peek () {
-		assert (_stack.size > 0);
-		return _stack.get (_stack.size - 1);
+	private Object peek (int offset = -1) {
+		assert (_stack.size >= - offset);
+		return _stack.get (_stack.size + offset);
 	}
 
 	private Object pop () {
@@ -127,6 +127,86 @@ public class Valadoc.DocumentationParser : Object, ResourceLocator {
 	}
 
 	private Rule multiline_run;
+	private int current_level = 0;
+	private int[] levels = new int[0];
+
+	private void new_list_item (Content.List.Bullet bullet) throws ParserError {
+		var new_item = _factory.create_list_item ();
+
+		Content.List list = null;
+		if (levels.length >= 1) {
+			if (current_level > levels[levels.length - 1]) {
+				list = _factory.create_list ();
+				list.bullet = bullet;
+
+				var current_item = peek () as ListItem;
+				current_item.sub_list = list;
+				push (list);
+
+				levels += current_level;
+			} else {
+				bool poped_some_lists = false;
+				while (current_level < levels[levels.length - 1]) {
+					// Pop current item and list
+					pop ();
+					pop ();
+					levels.resize (levels.length - 1);
+					poped_some_lists = true;
+				}
+				list = peek (-2) as Content.List;
+
+				if (!poped_some_lists && bullet == Content.List.Bullet.NONE) {
+					((InlineContent) peek ()).content.add (_factory.create_text (" "));
+					return;
+				} else if (list.bullet != bullet) {
+					_parser.error ("Invalid bullet type '%s': expected '%s'".printf (bullet_type_string (bullet), bullet_type_string (list.bullet)));
+					return;
+				}
+
+				pop ();
+			}
+		} else {
+			list = _factory.create_list ();
+			list.bullet = bullet;
+
+			((BlockContent) peek ()).content.add (list);
+			push (list);
+
+			levels = new int[0];
+			levels += current_level;
+		}
+
+		list.items.add (new_item);
+		push (new_item);
+	}
+
+	private string bullet_type_string (Content.List.Bullet bullet) {
+		switch (bullet) {
+		case Content.List.Bullet.NONE:
+			return ".";
+		case Content.List.Bullet.UNORDERED:
+			return "*";
+		case Content.List.Bullet.ORDERED_NUMBER:
+			return "1.";
+		case Content.List.Bullet.ORDERED_LOWER_CASE_ALPHA:
+			return "a.";
+		case Content.List.Bullet.ORDERED_UPPER_CASE_ALPHA:
+			return "A.";
+		case Content.List.Bullet.ORDERED_LOWER_CASE_ROMAN:
+			return "i.";
+		case Content.List.Bullet.ORDERED_UPPER_CASE_ROMAN:
+			return "I.";
+		}
+		return "";
+	}
+
+	private void finish_list () {
+		while (peek () is ListItem) {
+			pop ();
+			pop ();
+			levels.resize (levels.length - 1);
+		}
+	}
 
 	private void init_rules () {
 		// Inline rules
@@ -153,8 +233,6 @@ public class Valadoc.DocumentationParser : Object, ResourceLocator {
 					Rule.many ({
 						Rule.one_of ({
 							word,
-							TokenType.STAR.action (add_text),
-							TokenType.SHARP.action (add_text),
 							TokenType.LESS_THAN.action (add_text),
 							TokenType.GREATER_THAN.action (add_text),
 							TokenType.ALIGN_RIGHT.action (add_text),
@@ -287,36 +365,37 @@ public class Valadoc.DocumentationParser : Object, ResourceLocator {
 			.set_start (() => { push (_factory.create_source_code ()); })
 			.set_reduce (() => { ((BlockContent) peek ()).content.add ((Block) pop ()); });
 
-		Rule list_item =
+		Rule indented_item =
 			Rule.seq ({
 				Rule.many ({
-					TokenType.SPACE.action ((token) => { ((ListItem) peek ()).level++; })
-				}),
-				Rule.one_of ({
-					TokenType.STAR.action ((token) => { ((ListItem) peek ()).bullet = ListItem.Bullet.UNORDERED; }),
-					TokenType.SHARP.action ((token) => { ((ListItem) peek ()).bullet = ListItem.Bullet.ORDERED; }),
-					TokenType.str (".").action ((token) => { ((ListItem) peek ()).bullet = ListItem.Bullet.NONE; }),
-					TokenType.str ("I.").action ((token) => { ((ListItem) peek ()).bullet = ListItem.Bullet.ORDERED_LATIN; }),
-					TokenType.str ("A.").action ((token) => { ((ListItem) peek ()).bullet = ListItem.Bullet.ORDERED_CAPITAL; }),
-					TokenType.str ("1.").action ((token) => { ((ListItem) peek ()).bullet = ListItem.Bullet.ORDERED_NUMBER; }),
-					TokenType.str ("a.").action ((token) => { ((ListItem) peek ()).bullet = ListItem.Bullet.ORDERED_LOWER_CASE; })
+					TokenType.SPACE.action ((token) => { current_level++; })
 				}),
+				Rule.option ({
+					Rule.one_of ({
+						TokenType.str (".").action ((token) => { new_list_item (Content.List.Bullet.NONE); }),
+						TokenType.str ("*").action ((token) => { new_list_item (Content.List.Bullet.UNORDERED); }),
+						TokenType.str ("#").action ((token) => { new_list_item (Content.List.Bullet.ORDERED); }),
+						TokenType.str ("1.").action ((token) => { new_list_item (Content.List.Bullet.ORDERED_NUMBER); }),
+						TokenType.str ("a.").action ((token) => { new_list_item (Content.List.Bullet.ORDERED_LOWER_CASE_ALPHA); }),
+						TokenType.str ("A.").action ((token) => { new_list_item (Content.List.Bullet.ORDERED_UPPER_CASE_ALPHA); }),
+						TokenType.str ("i.").action ((token) => { new_list_item (Content.List.Bullet.ORDERED_LOWER_CASE_ROMAN); }),
+						TokenType.str ("I.").action ((token) => { new_list_item (Content.List.Bullet.ORDERED_UPPER_CASE_ROMAN); })
+					}),
+					TokenType.SPACE
+				})
+				.set_skip (() => { new_list_item (Content.List.Bullet.NONE); }),
 				run,
 				TokenType.EOL
 			})
-			.set_name ("ListItem")
-			.set_start (() => { push (_factory.create_list_item ()); })
-			.set_reduce (() => { ((Content.List) peek ()).items.add ((ListItem) pop ()); });
-		Rule list =
-			Rule.seq ({
-				Rule.many ({
-					list_item
-				}),
-				TokenType.EOL
+			.set_name ("IndentedItem")
+			.set_start (() => { current_level = 0; });
+
+		Rule indented_blocks =
+			Rule.many ({
+				indented_item
 			})
-			.set_name ("List")
-			.set_start (() => { push (_factory.create_list ()); })
-			.set_reduce (() => { ((BlockContent) peek ()).content.add ((Block) pop ()); });
+			.set_name ("IndentedBlocks")
+			.set_reduce (() => { finish_list (); });
 
 		Rule table_cell_attributes =
 			Rule.seq ({
@@ -432,7 +511,7 @@ public class Valadoc.DocumentationParser : Object, ResourceLocator {
 		Rule blocks =
 			Rule.one_of ({
 				source_code,
-				list,
+				indented_blocks,
 				table,
 				headline,
 				paragraph
diff --git a/src/libvaladoc/documentation/wikiscanner.vala b/src/libvaladoc/documentation/wikiscanner.vala
index 3f0c8df..47640a7 100644
--- a/src/libvaladoc/documentation/wikiscanner.vala
+++ b/src/libvaladoc/documentation/wikiscanner.vala
@@ -208,14 +208,6 @@ public class Valadoc.WikiScanner : Object, Scanner {
 				}
 				break;
 
-			case '*':
-				emit_token (TokenType.STAR);
-				break;
-
-			case '#':
-				emit_token (TokenType.SHARP);
-				break;
-
 			case '-':
 				if (_last_char.isalnum () || get_next_char ().isalnum ()) {
 					append_char (c);
@@ -392,4 +384,3 @@ public class Valadoc.WikiScanner : Object, Scanner {
 		}
 	}
 }
-
diff --git a/src/libvaladoc/html/htmlmarkupwriter.vala b/src/libvaladoc/html/htmlmarkupwriter.vala
index 004a704..d5c56c4 100755
--- a/src/libvaladoc/html/htmlmarkupwriter.vala
+++ b/src/libvaladoc/html/htmlmarkupwriter.vala
@@ -86,6 +86,7 @@ public class Valadoc.Html.MarkupWriter : Valadoc.MarkupWriter {
 			|| name == "h3"
 			|| name == "h4"
 			|| name == "h5"
+			|| name == "li"
 			|| name == "span"
 			|| name == "code"
 			|| name == "b"
diff --git a/src/libvaladoc/html/htmlrenderer.vala b/src/libvaladoc/html/htmlrenderer.vala
index e02076b..6ff7d49 100755
--- a/src/libvaladoc/html/htmlrenderer.vala
+++ b/src/libvaladoc/html/htmlrenderer.vala
@@ -225,9 +225,50 @@ public class Valadoc.Html.HtmlRenderer : ContentRenderer {
 	}
 
 	public override void visit_list (Content.List element) {
+		string list_type = null;
+		string bullet_type = null;
+		string css_class = null;
+		switch (element.bullet) {
+		case Content.List.Bullet.NONE:
+			list_type = "ul";
+			css_class = "no_bullet";
+			break;
+		case Content.List.Bullet.UNORDERED:
+			list_type = "ul";
+			break;
+		case Content.List.Bullet.ORDERED:
+			list_type = "ol";
+			break;
+		case Content.List.Bullet.ORDERED_NUMBER:
+			list_type = "ol";
+			bullet_type = "1";
+			break;
+		case Content.List.Bullet.ORDERED_LOWER_CASE_ALPHA:
+			list_type = "ol";
+			bullet_type = "a";
+			break;
+		case Content.List.Bullet.ORDERED_UPPER_CASE_ALPHA:
+			list_type = "ol";
+			bullet_type = "A";
+			break;
+		case Content.List.Bullet.ORDERED_LOWER_CASE_ROMAN:
+			list_type = "ol";
+			bullet_type = "i";
+			break;
+		case Content.List.Bullet.ORDERED_UPPER_CASE_ROMAN:
+			list_type = "ol";
+			bullet_type = "I";
+			break;
+		}
+		writer.start_tag (list_type, {"class", css_class, "type", bullet_type});
+		element.accept_children (this);
+		writer.end_tag (list_type);
 	}
 
 	public override void visit_list_item (ListItem element) {
+		writer.start_tag ("li");
+		element.accept_children (this);
+		writer.end_tag ("li");
 	}
 
 	public override void visit_page (Page element) {
diff --git a/src/libvaladoc/parser/optionalrule.vala b/src/libvaladoc/parser/optionalrule.vala
index 2498c76..693b581 100644
--- a/src/libvaladoc/parser/optionalrule.vala
+++ b/src/libvaladoc/parser/optionalrule.vala
@@ -57,7 +57,7 @@ internal class Valadoc.OptionalRule : Rule {
 			if (try_to_apply (_scheme, token, parser, out handled)) {
 				return handled;
 			} else {
-				do_reduce (parser);
+				do_skip (parser);
 				return false;
 			}
 		} else {
diff --git a/src/libvaladoc/parser/rule.vala b/src/libvaladoc/parser/rule.vala
index abbaeff..b63495c 100644
--- a/src/libvaladoc/parser/rule.vala
+++ b/src/libvaladoc/parser/rule.vala
@@ -54,6 +54,7 @@ public abstract class Valadoc.Rule : Object {
 	private string? _name = null;
 	private Action _start_action;
 	private Action _reduce_action;
+	private Action _skip_action;
 
 	public string name { get { return _name; } }
 
@@ -74,6 +75,11 @@ public abstract class Valadoc.Rule : Object {
 		return this;
 	}
 
+	public Rule set_skip (Action action) {
+		_skip_action = action;
+		return this;
+	}
+
 	public enum Forward {
 		NONE, PARENT, CHILD
 	}
@@ -147,4 +153,10 @@ public abstract class Valadoc.Rule : Object {
 		}
 		parser.reduce ();
 	}
+
+	protected void do_skip (ParserCallback parser) throws ParserError {
+		if (_skip_action != null) {
+			_skip_action ();
+		}
+	}
 }
diff --git a/src/libvaladoc/parser/sequencerule.vala b/src/libvaladoc/parser/sequencerule.vala
index 3cad1a5..b2f9d5a 100644
--- a/src/libvaladoc/parser/sequencerule.vala
+++ b/src/libvaladoc/parser/sequencerule.vala
@@ -91,6 +91,8 @@ internal class Valadoc.SequenceRule : Rule {
 			}
 			if (!is_optional_rule (scheme_element)) {
 				break;
+			} else {
+				((Rule) scheme_element).do_skip (parser);
 			}
 			state.index++;
 		} while (state.index < _scheme.length);
diff --git a/src/libvaladoc/parser/tokentype.vala b/src/libvaladoc/parser/tokentype.vala
index 6ebc19a..598aac3 100644
--- a/src/libvaladoc/parser/tokentype.vala
+++ b/src/libvaladoc/parser/tokentype.vala
@@ -38,8 +38,6 @@ public class Valadoc.TokenType : Object {
 	public static TokenType EQUAL_4;
 	public static TokenType EQUAL_5;
 	public static TokenType MINUS;
-	public static TokenType STAR;
-	public static TokenType SHARP;
 	public static TokenType LESS_THAN;
 	public static TokenType GREATER_THAN;
 	public static TokenType ALIGN_TOP;
@@ -79,8 +77,6 @@ public class Valadoc.TokenType : Object {
 			EQUAL_4 = new TokenType.basic ("=====");
 			EQUAL_5 = new TokenType.basic ("======");
 			MINUS = new TokenType.basic ("-");
-			STAR = new TokenType.basic ("*");
-			SHARP = new TokenType.basic ("#");
 			LESS_THAN = new TokenType.basic ("<");
 			GREATER_THAN = new TokenType.basic (">");
 			ALIGN_TOP = new TokenType.basic ("^");



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]