extradoc.py: Correct handling of nested #+IF conditionals.

master
François Pinard 13 years ago
parent 71dca66b8e
commit c21cca6d3b
  1. 46
      extradoc.py

@ -45,12 +45,15 @@ import tokenize
encoding = 'UTF-8' encoding = 'UTF-8'
# State constants for #+IF processing. # Within an #+IF [#+ELIF]... [#+ELSE] #+ENDIF structure, the state may
# - The current state is stacked when seeing an #+IF, and unstacked when seeing an #+ENDIF. # vary between FALSE, TRUE and SKIP. The state before the structure is
# - If the state ever becomes SKIP in an #+IF, it remains that way until the matching #+ENDIF. # saved on entry, and restored on exit. The state is TRUE at the
# - If not SKIP, #+IF sets the state to either TRUE or FALSE. # beginning of a file. If the state before stacking was TRUE, it starts
# - If not SKIP, #+ELIF sets the state to SKIP if it was TRUE, or to either TRUE or FALSE. # as FALSE within the structure; otherwise, the state starts as SKIP.
# - If not SKIP, #ELSE sets the state to TRUE if FALSE, or to FALSE if TRUE. # States may only go from FALSE to any other state; or else, necessarily
# to SKIP. Within a structure, the state can be TRUE at most once,
# indicating that the tested condition was true. It can be FALSE
# earlier in the structure, and may only be SKIP after the TRUE segment.
FALSE, TRUE, SKIP = range(3) FALSE, TRUE, SKIP = range(3)
@ -105,8 +108,6 @@ class Main:
sys.exit("File %s.org exists and -o not specified." % self.prefix) sys.exit("File %s.org exists and -o not specified." % self.prefix)
# Prepare the work. # Prepare the work.
self.stack = []
self.state = TRUE
if not self.split and (self.html or self.org or self.pdf): if not self.split and (self.html or self.org or self.pdf):
self.org_file = open(self.prefix + '.org', 'w') self.org_file = open(self.prefix + '.org', 'w')
else: else:
@ -154,8 +155,6 @@ class Main:
def extract_org_fragments(self, file, name): def extract_org_fragments(self, file, name):
# LEVEL not None means inhibit copy from that header level on. # LEVEL not None means inhibit copy from that header level on.
level = None level = None
self.stack = []
self.state = TRUE
for line in self.each_org_line(file, name): for line in self.each_org_line(file, name):
if line.startswith('#+FILE:'): if line.startswith('#+FILE:'):
if self.split: if self.split:
@ -182,8 +181,6 @@ class Main:
level = None level = None
if level is None and self.org_file is not None: if level is None and self.org_file is not None:
self.org_file.write(line + '\n') self.org_file.write(line + '\n')
if self.stack:
sys.stderr.write("%s: Some #+ENDIF might be missing.\n" % name)
def each_org_line(self, file, name): def each_org_line(self, file, name):
@ -193,6 +190,8 @@ class Main:
def warn(diagnostic): def warn(diagnostic):
sys.stderr.write('%s:%s %s\n' % (name, line_no, diagnostic)) sys.stderr.write('%s:%s %s\n' % (name, line_no, diagnostic))
self.stack = []
self.state = TRUE
for (code, text, (line_no, _), _, _ for (code, text, (line_no, _), _, _
) in tokenize.generate_tokens(file.readline): ) in tokenize.generate_tokens(file.readline):
if code == tokenize.STRING: if code == tokenize.STRING:
@ -205,19 +204,22 @@ class Main:
for line in text.splitlines(): for line in text.splitlines():
if line.startswith('#+IF '): if line.startswith('#+IF '):
self.stack.append(self.state) self.stack.append(self.state)
if self.state != SKIP: if self.state == TRUE:
value = eval(line[5:], self.context) value = eval(line[5:], self.context)
self.state = if_bool(value) self.state = if_bool(value)
else:
self.state = SKIP
elif line.startswith('#+ELIF '): elif line.startswith('#+ELIF '):
if self.state != SKIP: if self.state == FALSE:
if self.state == TRUE: value = eval(line[7:], self.context)
self.state = SKIP self.state = if_bool(value)
else: else:
value = eval(line[7:], self.context) self.state = SKIP
self.state = if_bool(value)
elif line == '#+ELSE': elif line == '#+ELSE':
if self.state != SKIP: if self.state == FALSE:
self.state = if_bool(self.state == FALSE) self.state = TRUE
else:
self.state = SKIP
elif line == '#+ENDIF': elif line == '#+ENDIF':
if self.stack: if self.stack:
self.state = self.stack.pop() self.state = self.stack.pop()
@ -227,6 +229,8 @@ class Main:
if line.startswith('#+FILE:') and not self.split: if line.startswith('#+FILE:') and not self.split:
warn("#+FILE directive, and not -s.") warn("#+FILE directive, and not -s.")
yield line yield line
if self.stack:
sys.stderr.write("%s: Some #+ENDIF might be missing.\n" % name)
def launch_emacs(self, args): def launch_emacs(self, args):
import subprocess import subprocess

Loading…
Cancel
Save