Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Comparing changes

Choose two branches to see what's changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: now/nmc
base: 95ce9a6176
...
head fork: now/nmc
compare: d88d20a73a
Checking mergeability… Don't worry, you can still create the pull request.
  • 3 commits
  • 4 files changed
  • 0 commit comments
  • 1 contributor
Commits on May 17, 2012
Nikolai Weibull Remove previous 38fbcd4
Commits on May 22, 2012
Nikolai Weibull Fix handling of newlines 28c1234
Nikolai Weibull Add handling of footnote blocks in grammar d88d20a
Showing with 148 additions and 20 deletions.
  1. +24 −1 src/grammar.y
  2. +34 −18 src/parser.c
  3. +0 −1  src/parser.h
  4. +90 −0 test/testsuite.at
View
25 src/grammar.y
@@ -23,12 +23,15 @@
%token CONTINUATION
%token BLOCKSEPARATOR
%token ENUMERATION
+%token FOOTNOTE
%token SECTION
%token INDENT
%token DEDENT
%type <buffer> words
%type <node> title oblockssections0 oblockssections blockssections blocks block paragraph sections section oblocks enumeration enumerationitem
+%type <node> blockfootnotes
+%type <node> blockfootnote
%union {
const xmlChar *string;
@@ -103,6 +106,20 @@ append(xmlBufferPtr buffer, const xmlChar *string, int length)
return buffer;
}
+static xmlNodePtr
+footnote(xmlNodePtr footnotes, xmlNodePtr blocks)
+{
+ xmlNodePtr last = xmlGetLastChild(blocks);
+ if (!xmlStrEqual(last->name, BAD_CAST "footnotes")) {
+ xmlUnlinkNode(last);
+ return sibling(blocks, child(footnotes, last));
+ }
+ xmlAddChildList(last, footnotes->children);
+ footnotes->children = NULL;
+ xmlFreeNode(footnotes);
+ return blocks;
+}
+
#define YYPRINT(file, type, value) print_token_value(file, type, value)
static void
print_token_value(FILE *file, int type, YYSTYPE value)
@@ -133,11 +150,17 @@ blockssections: blocks
| sections;
blocks: block
-| blocks BLOCKSEPARATOR block { $$ = sibling($1, $3); };
+| blocks BLOCKSEPARATOR block { $$ = sibling($1, $3); }
+| blocks BLOCKSEPARATOR blockfootnotes { $$ = footnote($3, $1); };
block: paragraph
| enumeration;
+blockfootnotes: blockfootnote { $$ = child(node("footnotes"), $1); }
+| blockfootnotes blockfootnote { $$ = child($1, $2); };
+
+blockfootnote: FOOTNOTE words { $$ = content("footnote", $2); };
+
paragraph: PARAGRAPH words { $$ = content("p", $2); };
enumeration: enumerationitem { $$ = child(node("enumeration"), $1); }
View
52 src/parser.c
@@ -24,7 +24,6 @@ nmc_parse(const xmlChar *input)
parser.dedents = 0;
parser.indent = 0;
parser.bol = false;
- parser.previous = ERROR;
parser.doc = xmlNewDoc(BAD_CAST "1.0");
skip(&parser, ' ');
@@ -38,7 +37,6 @@ static int
token(struct nmc_parser *parser, const xmlChar *end, int type)
{
parser->p = end;
- parser->previous = type;
return type;
}
@@ -50,18 +48,34 @@ substring(struct nmc_parser *parser, YYSTYPE *value, const xmlChar *end, int typ
return token(parser, end, type);
}
+static int
+dedent(struct nmc_parser *parser, const xmlChar *end)
+{
+ /* TODO: assert(parser->dedents > 0); */
+ parser->dedents--;
+ return token(parser, end, DEDENT);
+}
+
+static int
+dedents(struct nmc_parser *parser, const xmlChar *end, int spaces)
+{
+ parser->dedents = (parser->indent - spaces) / 2;
+ parser->indent -= 2 * parser->dedents;
+ /* TODO: assert(parser->indent >= 0); */
+ return dedent(parser, end);
+}
+
int
nmc_parser_lex(struct nmc_parser *parser, YYSTYPE *value)
{
const xmlChar *end = parser->p;
-dedents:
- if (parser->dedents > 0) {
- parser->dedents--;
- return token(parser, end, DEDENT);
- }
+ if (parser->dedents > 0)
+ return dedent(parser, end);
+bol:
if (parser->bol) {
+ /* TODO Make this into a function */
parser->bol = false;
if (xmlStrncmp(end, BAD_CAST " ", 2) == 0)
return token(parser, end + 2, PARAGRAPH);
@@ -69,6 +83,7 @@ nmc_parser_lex(struct nmc_parser *parser, YYSTYPE *value)
return token(parser, end + xmlUTF8Size(BAD_CAST "§ "), SECTION);
else if (xmlStrncmp(end, BAD_CAST "", xmlUTF8Size(BAD_CAST "")) == 0)
return token(parser, end + xmlUTF8Size(BAD_CAST ""), ENUMERATION);
+ */
else if (*end == '\0')
return END;
else
@@ -99,23 +114,24 @@ nmc_parser_lex(struct nmc_parser *parser, YYSTYPE *value)
return token(parser, parser->p + parser->indent, INDENT);
} else if (spaces < parser->indent && spaces % 2 == 0) {
parser->want = ERROR;
- parser->dedents = (parser->indent - spaces) / 2;
- parser->indent -= 2 * parser->dedents;
- goto dedents;
+ return dedents(parser, end, spaces);
} else {
parser->want = ERROR;
return token(parser, parser->p, BLOCKSEPARATOR);
}
} else {
- if (end != parser->p)
+ int spaces = end - parser->p;
+ if (spaces > parser->indent) {
return token(parser, end, CONTINUATION);
- else if (parser->indent > 0) {
- /* TODO: Not quite sure about this test. We
- * might want to check if end == '\0' &&
- * parser->indent > 0 instead. */
- parser->dedents = parser->indent / 2;
- parser->indent = 0;
- goto dedents;
+ } else if (spaces < parser->indent) {
+ if (spaces % 2 != 0)
+ return token(parser, end, CONTINUATION);
+ parser->bol = true;
+ return dedents(parser, end, spaces);
+ } else {
+ parser->bol = true;
+ parser->p = end;
+ goto bol;
}
}
}
View
1  src/parser.h
@@ -8,7 +8,6 @@ struct nmc_parser
int indent;
int dedents;
bool bol;
- int previous;
int want;
xmlDocPtr doc;
};
View
90 test/testsuite.at
@@ -102,6 +102,48 @@ AT_NMC_CHECK([title],
AT_CLEANUP
+AT_SETUP([Document consisting of a title followed by a section containing two paragraphs])
+
+AT_DATA([title],
+[[Title
+
+§ Section
+
+ Paragraph1
+
+ Paragraph2
+]])
+
+AT_NMC_CHECK([title],
+[[ <title>Title</title>
+ <section>
+ <title>Section</title>
+ <p>Paragraph1</p>
+ <p>Paragraph2</p>
+ </section>]])
+
+AT_CLEANUP
+
+AT_SETUP([Document consisting of a title followed by a section containing a multi-line paragraph])
+
+AT_DATA([title],
+[[Title
+
+§ Section
+
+ Line1
+ Line2
+]])
+
+AT_NMC_CHECK([title],
+[[ <title>Title</title>
+ <section>
+ <title>Section</title>
+ <p>Line1 Line2</p>
+ </section>]])
+
+AT_CLEANUP
+
AT_SETUP([Document consisting of a title followed by two sections])
AT_DATA([title],
@@ -152,3 +194,51 @@ AT_NMC_CHECK([title],
<p>Paragraph2</p>]])
AT_CLEANUP
+
+AT_SETUP([Document consisting of a title followed by a two-item enumeration])
+
+AT_DATA([title],
+[[Title
+
+• Item1
+• Item2
+]])
+
+AT_NMC_CHECK([title],
+[[ <title>Title</title>
+ <enumeration>
+ <item>
+ <p>Item1</p>
+ </item>
+ <item>
+ <p>Item2</p>
+ </item>
+ </enumeration>]])
+
+AT_CLEANUP
+
+AT_SETUP([Document consisting of a title followed by a two-item enumeration, the first containing two paragraphs])
+
+AT_DATA([title],
+[[Title
+
+• Line1
+ Line2
+
+ Paragraph2
+• Item2
+]])
+
+AT_NMC_CHECK([title],
+[[ <title>Title</title>
+ <enumeration>
+ <item>
+ <p>Line1 Line2</p>
+ <p>Paragraph2</p>
+ </item>
+ <item>
+ <p>Item2</p>
+ </item>
+ </enumeration>]])
+
+AT_CLEANUP

No commit comments for this range

Something went wrong with that request. Please try again.