Implement a stack of position markers to delay the insertion of an opening tag until...
authorNick Downing <nick@ndcode.org>
Sat, 19 Jan 2019 14:31:14 +0000 (01:31 +1100)
committerNick Downing <nick@ndcode.org>
Sat, 19 Jan 2019 14:31:14 +0000 (01:31 +1100)
bootstrap/markup.py
bootstrap/parse.y
bootstrap/scan.l

index 543338e..d65f9d3 100755 (executable)
@@ -4,7 +4,7 @@ import lex_yy
 import y_tab
 import sys
 
-lex_yy.piece_append('<root>\n  <AST ref=\"0\"><AST_Section1>')
 y_tab.yyparse()
+lex_yy.piece_insert(0, '<root>\n  <AST ref=\"0\">')
 lex_yy.piece_append('</AST>\n</root>\n')
 sys.stdout.write(''.join(lex_yy.piece))
index 8f50edd..9d60865 100644 (file)
@@ -67,7 +67,7 @@
 %%
 
 goal
-  : initlex sect1 sect1end sect2 initforrule
+  : initlex sect1 sect1end sect2 sect2end initforrule
     {
       #def_rule = None
       #pat = cclinit()
@@ -84,6 +84,10 @@ goal
       #else:
       #  add_action('ECHO')
       #add_action(';\n\tYY_BREAK]]\n')
+      insert_before(4, '</AST_Section2>')
+      insert_after(2, '<AST_Section2>')
+      insert_before(2, '</AST_Section1>')
+      insert_before(0, '<AST_Section1>')
     }
   ;
 
@@ -121,6 +125,20 @@ sect1end
     }
   ;
 
+/* Nick */
+sect2end
+  : SECTEND
+    {
+      global yychar
+      if yychar == YYEMPTY:
+        yychar = lex_yy.flexscan()
+        #print('yyy yychar', yychar, 'yylval', yylval, 'yylloc', yylloc, 'lex_yy.yytext', yytext)
+      insert_before(1, '</AST_Section3>')
+      insert_after(0, '<AST_Section3>')
+    }
+  |
+  ;
+
 startconddecl
   : SCDECL
     {
index fbfc040..56278b7 100644 (file)
@@ -6,6 +6,7 @@
 
   piece = []
   piece0 = 0
+  markup_stack = []
 
   # these should be yylex()-local, but moved to here, see further down:
   bracelevel = 0
@@ -80,8 +81,8 @@ M4QEND      "]""]"
     yy_push_state(CODEBLOCK)
     indented_code = True
     #add_action(yytext)
-    piece_append('<AST_Section1Or2_CodeBlock>')
-    piece_append('<AST_Text>')
+    markup_stack.append(len(piece)) # <AST_Section1Or2_CodeBlock>
+    markup_stack.append(len(piece)) # <AST_Text>
   }
   ^"/*" {
     #add_action('/*[' '[')
@@ -98,9 +99,9 @@ M4QEND      "]""]"
     #add_action('[' '[')
     yy_push_state(CODEBLOCK)
     indented_code = False
-    piece_append('<AST_Section1Or2_CodeBlock>')
+    markup_stack.append(len(piece)) # <AST_Section1Or2_CodeBlock>
     piece_flush(len(yytext))
-    piece_append('<AST_Text>')
+    markup_stack.append(len(piece)) # <AST_Text>
   }
   ^"%top"[[:blank:]]*"{"[[:blank:]]*{NL} {
     global brace_start_line, brace_depth
@@ -122,12 +123,7 @@ M4QEND      "]""]"
     #mark_defs1()
     #line_directive_out(None, 1)
     BEGIN(SECT2PROLOG)
-    piece_append('</AST_Section1>')
-    piece_pack()
-    piece_escape(yytext)
-    piece_append('<AST_Section2>')
-    piece_pack()
-    return ~y_tab.SECTEND
+    return y_tab.SECTEND
   }
 
   ^"%pointer".*{NL} {
@@ -235,12 +231,14 @@ M4QEND      "]""]"
 <CODEBLOCK>{
   ^"%}".*{NL} {
     state.linenum += 1
+    piece_insert(markup_stack.pop(), '<AST_Text>')
     piece_append('</AST_Text>')
     piece_flush(len(yytext))
     yy_pop_state()
     #add_action(']' ']')
     #if not indented_code:
     #  line_directive_out(None, 0)
+    piece_insert(markup_stack.pop(), '<AST_Section1Or2_CodeBlock>')
     piece_append('</AST_Section1Or2_CodeBlock>')
   }
   [^\n%\[\]]*                  #add_action(yytext)
@@ -250,11 +248,13 @@ M4QEND      "]""]"
     #add_action(yytext)
     if indented_code:
       piece_flush(len(yytext))
+      piece_insert(markup_stack.pop(), '<AST_Text>')
       piece_append('</AST_Text>')
       yy_pop_state()
       #add_action(']' ']')
       #if not indented_code:
       #  line_directive_out(None, 0)
+      piece_insert(markup_stack.pop(), '<AST_Section1Or2_CodeBlock>')
       piece_append('</AST_Section1Or2_CodeBlock>')
   }
 }
@@ -1287,8 +1287,8 @@ M4QEND      "]""]"
     yy_push_state(CODEBLOCK)
     indented_code = True
     #add_action(yytext)
-    piece_append('<AST_Section1Or2_CodeBlock>')
-    piece_append('<AST_Text>')
+    markup_stack.append(len(piece)) # <AST_Section1Or2_CodeBlock>
+    markup_stack.append(len(piece)) # <AST_Text>
   }
 
   ^{NOT_WS}.* {
@@ -1306,8 +1306,8 @@ M4QEND      "]""]"
       yy_push_state(CODEBLOCK)
       indented_code = True
       #add_action(yytext)
-      piece_append('<AST_Section1Or2_CodeBlock>')
-      piece_append('<AST_Text>')
+      markup_stack.append(len(piece)) # <AST_Section1Or2_CodeBlock>
+      markup_stack.append(len(piece)) # <AST_Text>
   }
 
   .                            #add_action(yytext)
@@ -1320,8 +1320,6 @@ M4QEND      "]""]"
     #mark_prolog()
     sectnum = 0
     piece_pack()
-    piece_append('</AST_Section2>')
-    piece_pack()
     return ~YY_NULL
   }
 }
@@ -1336,9 +1334,9 @@ M4QEND      "]""]"
     bracelevel = 1
     BEGIN(PERCENT_BRACE_ACTION)
     piece_flush(len(yytext) - 2)
-    piece_append('<AST_Section1Or2_CodeBlock>')
+    markup_stack.append(len(piece)) # <AST_Section1Or2_CodeBlock>
     piece_flush(2)
-    piece_append('<AST_Text>')
+    markup_stack.append(len(piece)) # <AST_Text>
   }
 
   ^{OPTWS}"<" {
@@ -1369,12 +1367,12 @@ M4QEND      "]""]"
     bracelevel = 1
     BEGIN(PERCENT_BRACE_ACTION)
     piece_flush(len(yytext) - 2)
-    piece_append('<AST_Section2_Rule_Action>')
+    markup_stack.append(len(piece)) # <AST_Section2_Rule_Action>
     assert state.in_rule # should do error message here
     doing_rule_action = True
     state.in_rule = False
     piece_flush(2)
-    piece_append('<AST_Text>')
+    markup_stack.append(len(piece)) # <AST_Text>
   }
   {WS}"|".*{NL} {
     if state._sf_stk[-1] & 4:
@@ -1446,9 +1444,7 @@ M4QEND      "]""]"
     sectnum = 3
     BEGIN(SECT3_NOESCAPE if state.no_section3_escape else SECT3)
     #outn('/* Begin user sect3 */')
-    piece_append('</AST_Section2>')
-    piece_flush(len(yytext))
-    piece_append('<AST_Section3>')
+    return y_tab.SECTEND
   }
 
   "["({FIRST_CCL_CHAR}|{CCL_EXPR})({CCL_CHAR}|{CCL_EXPR})* {
@@ -1537,15 +1533,6 @@ M4QEND      "]""]"
   . {
     y_tab.yylval = ord(yytext[0])
     return y_tab.CHAR
-  }
-
-       /* Nick added this rule for consistency with rest of scanner */
-  <<EOF>> {
-    sectnum = 0
-    piece_pack()
-    piece_append('</AST_Section2>')
-    piece_pack()
-    return ~YY_NULL
   }
 }
 
@@ -1816,6 +1803,7 @@ M4QEND      "]""]"
   {OPTWS}"%}".* {
     global bracelevel
     bracelevel = 0
+    piece_insert(markup_stack.pop(), '<AST_Text>')
     piece_append('</AST_Text>')
   }
 
@@ -1849,9 +1837,11 @@ M4QEND      "]""]"
       doing_rule_action = False
       BEGIN(SECT2)
       if doing_codeblock:
+        piece_insert(markup_stack.pop(), '<AST_Section1Or2_CodeBlock>')
         piece_append('</AST_Section1Or2_CodeBlock>')
         doing_codeblock = False
       else:
+        piece_insert(markup_stack.pop(), '<AST_Section2_Rule_Action>')
         piece_append('</AST_Section2_Rule_Action>')
         return ord('\n')
   }
@@ -1957,8 +1947,6 @@ M4QEND      "]""]"
   <<EOF>> {
     sectnum = 0
     piece_pack()
-    piece_append('</AST_Section3>')
-    piece_pack()
     return ~YY_NULL
   }
 }
@@ -1970,8 +1958,6 @@ M4QEND      "]""]"
   <<EOF>> {
     sectnum = 0
     piece_pack()
-    piece_append('</AST_Section3>')
-    piece_pack()
     return ~YY_NULL
   }
 }