Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Add support for continuation lines

This isn’t final, just an example implementation.  The future will make
the separation between INDENT, PARAGRAPH, and CONTINUATION clearer by
only returning INDENT if the previous token was BLANKLINE.
  • Loading branch information...
commit c65426262cc5d60c9411142858a044975bbd9a58 1 parent 51e376c
authored May 16, 2012
20  src/grammar.y
@@ -13,6 +13,7 @@
13 13
 %parse-param {struct nmc_parser *parser}
14 14
 %lex-param {struct nmc_parser *parser}
15 15
 %name-prefix "nmc_grammar_"
  16
+%debug
16 17
 %error-verbose
17 18
 
18 19
 %token END 0 "end of file"
@@ -20,11 +21,12 @@
20 21
 %token <substring> WORD
21 22
 %token <substring> BLANKLINE
22 23
 %token PARAGRAPH
  24
+%token CONTINUATION
23 25
 %token SECTION
24 26
 %token INDENT
25 27
 %token DEDENT
26 28
 
27  
-%type <buffer> words blanklines paragraphline oblanklines
  29
+%type <buffer> words blanklines oblanklines
28 30
 %type <node> title oblockssections blocks block paragraph sections section
29 31
 
30 32
 %union {
@@ -82,6 +84,7 @@ child(xmlNodePtr parent, xmlNodePtr child)
82 84
         return parent;
83 85
 }
84 86
 
  87
+/*
85 88
 static xmlNodePtr
86 89
 buffer_append(xmlNodePtr parent, xmlBufferPtr buffer)
87 90
 {
@@ -90,6 +93,15 @@ buffer_append(xmlNodePtr parent, xmlBufferPtr buffer)
90 93
         xmlBufferFree(buffer);
91 94
         return parent;
92 95
 }
  96
+*/
  97
+
  98
+#define YYPRINT(file, type, value) print_token_value(file, type, value)
  99
+static void
  100
+print_token_value(FILE *file, int type, YYSTYPE value)
  101
+{
  102
+        if (type == WORD)
  103
+                fprintf(file, "%.*s", value.substring.length, value.substring.string);
  104
+}
93 105
 }
94 106
 
95 107
 %%
@@ -100,6 +112,7 @@ title: words { $$ = buffer("title", $1); }
100 112
 
101 113
 words: WORD { $$ = xmlBufferCreate(); xmlBufferAdd($$, $1.string, $1.length); }
102 114
 | words WORD { $$ = $1; if ($$) { xmlBufferCCat($$, " "); xmlBufferAdd($$, $2.string, $2.length); } };
  115
+| words CONTINUATION WORD { $$ = $1; if ($$) { xmlBufferCCat($$, " "); xmlBufferAdd($$, $3.string, $3.length); } };
103 116
 
104 117
 oblockssections: /* empty */ { $$ = NULL; }
105 118
 | blanklines blocks { $$ = $2; };
@@ -114,10 +127,7 @@ blanklines: BLANKLINE { $$ = xmlBufferCreate(); xmlBufferAdd($$, $1.string, $1.l
114 127
 
115 128
 block: paragraph;
116 129
 
117  
-paragraph: paragraphline { $$ = buffer("p", $1); }
118  
-| paragraph paragraphline { $$ = buffer_append($1, $2); };
119  
-
120  
-paragraphline: PARAGRAPH words { $$ = $2; };
  130
+paragraph: PARAGRAPH words { $$ = buffer("p", $2); };
121 131
 
122 132
 sections: section
123 133
 | sections section { $$ = $1; xmlAddSibling($$, $2); };
5  src/nmc.c
@@ -2,12 +2,15 @@
2 2
 
3 3
 #include <libxml/tree.h>
4 4
 #include <stdbool.h>
  5
+#include <stdlib.h>
5 6
 #include <unistd.h>
6 7
 
7 8
 #include "grammar.h"
8 9
 #include "nmc.h"
9 10
 #include "parser.h"
10 11
 
  12
+extern int nmc_grammar_debug;
  13
+
11 14
 int
12 15
 main(UNUSED(int argc), UNUSED(char **argv))
13 16
 {
@@ -15,6 +18,8 @@ main(UNUSED(int argc), UNUSED(char **argv))
15 18
         ssize_t bytes = read(STDIN_FILENO, buffer, sizeof(buffer));
16 19
         buffer[bytes] = '\0';
17 20
 
  21
+        if (getenv("NMC_DEBUG"))
  22
+                nmc_grammar_debug = 1;
18 23
         xmlDocPtr doc = nmc_parse(BAD_CAST buffer);
19 24
         xmlSaveFormatFileEnc("-", doc, "UTF-8", 1);
20 25
         xmlFreeDoc(doc);
12  src/parser.c
@@ -68,25 +68,27 @@ nmc_parser_lex(struct nmc_parser *parser, YYSTYPE *value)
68 68
                         /* paragraph */
69 69
                 } else if (spaces == parser->indent + 4) {
70 70
                         parser->indent += 2;
71  
-                        parser->p = end - 2;
72  
-                        return INDENT;
  71
+                        return token(parser, end - 2, INDENT);
73 72
                 } else if (spaces < parser->indent && spaces % 2 == 0) {
74 73
                         parser->dedents = (parser->indent - spaces) / 2;
75 74
                         parser->indent -= 2 * parser->dedents;
76  
-                        parser->p = end;
77 75
                 } else if (end != parser->p)
78 76
                         return token(parser, end, ERROR);
79 77
         }
80 78
 
81 79
         if (parser->dedents > 0) {
82 80
                 parser->dedents--;
83  
-                return DEDENT;
  81
+                return token(parser, end, DEDENT);
84 82
         }
85 83
 
86 84
         if (parser->state == AFTER_INDENT) {
87 85
                 parser->state = OTHER;
88 86
                 if (xmlStrncmp(end, BAD_CAST "  ", 2) == 0)
89  
-                        return token(parser, end + 2, PARAGRAPH);
  87
+                        return token(parser, end + 2,
  88
+                                     end - 2 >= parser->input &&
  89
+                                     *(end - 1) == '\n' &&
  90
+                                     *(end - 2) != '\n' &&
  91
+                                     *(end - 2) != ' ' ? CONTINUATION : PARAGRAPH);
90 92
                 else if (xmlStrncmp(end, BAD_CAST "§ ", xmlUTF8Size(BAD_CAST "§ ")) == 0)
91 93
                         return token(parser, end + xmlUTF8Size(BAD_CAST "§ "), SECTION);
92 94
                 else if (parser->p == end)
12  test/testsuite.at
@@ -24,6 +24,18 @@ AT_NMC_CHECK([title],
24 24
 
25 25
 AT_CLEANUP
26 26
 
  27
+AT_SETUP([Document only consisting of a multi-line title])
  28
+
  29
+AT_DATA([title],
  30
+[[  Word1
  31
+  Word2
  32
+]])
  33
+
  34
+AT_NMC_CHECK([title],
  35
+[[  <title>Word1 Word2</title>]])
  36
+
  37
+AT_CLEANUP
  38
+
27 39
 AT_SETUP([Document consisting of a title followed by a paragraph])
28 40
 
29 41
 AT_DATA([title],

0 notes on commit c654262

Please sign in to comment.
Something went wrong with that request. Please try again.