html - 如何在流中标记 pyparsing 位置以便稍后返回?
问题描述
背景:
我正在尝试实现一种用于写小说的简单(?)标记语言。
这与通常的标记完全不同,因为语义以不同的原语为中心,特别是直接语音与列表相去甚远。
基本结构是众所周知的:@part{title}
,@chapter{title}
并且@scene[{title}]
具有通常的含义,并且 double-\n
表示分节符。
具体功能包括:
- @speach[speaker]{话语,可能很复杂}
- @stress{应该在视觉上增强的东西}
- @standout{应该有不同视觉增强的部分}
- @quotation[原作者]{可能是长块引用}
这应该被解析并翻译成不同的输出格式(例如:html 和 LaTeX)。
我有一个pyparsing
能够解析非平凡输入的语法。
问题是为 HTML 生成段落:
如前所述,段落以双换行符结尾,但基本上从前一段的结尾开始,除非某些顶级构造(例如:)@chapter
干预以中断序列。
第一个天真的尝试是在全局缓冲区中累积文本片段并在选定的点发出它们;这在逻辑上可行,但似乎多次pyparsing
调用它,因此我的全局缓冲区最终保留了相同的片段重复。ParseActions
我还没有找到一种方法来避免这种重复或以这样的方式标记“段落的开头”,以便我以后可以回到它来生成众所周知的<p>Long line, maybe containing @speech{possibly nested with @standout{!} and other constructs}</p>
(当然@standout
应该映射<b>!</b>
到@speech
某些特定的<div class="speech"></div>
)
处理此类问题的“最佳实践”是什么?
注意:LaTeX 代码生成的问题要少得多,因为段落只是以空行或\par
.
解决方案
您是否有可能将其改写为“稍后再回到开头”的问题,而是将其改写为“在我需要了解整个事情的情况下提前阅读”的问题?
我认为nestedExpr
这可能是一种让您提前阅读下一个完整标记的方法,然后通过解析操作重新解析内容以处理任何嵌套的标记指令。nestedExpr
将其解析的输入作为嵌套列表返回,但要将所有内容作为扁平字符串获取,请将其包装在originalTextFor
.
这是 pyparsing 示例中 simpleWiki.py 示例的返工:
import pyparsing as pp
wiki_markup = pp.Forward()
# a method that will construct and return a parse action that will
# do the proper wrapping in opening and closing HTML, and recursively call
# wiki_markup.transformString on the markup body text
def convert_markup_to_html(opening,closing):
def conversionParseAction(s, l, t):
return opening + wiki_markup.transformString(t[1][1:-1]) + closing
return conversionParseAction
# use a nestedExpr with originalTextFor to parse nested braces, but return the
# parsed text as a single string containing the outermost nested braces instead
# of a nested list of parsed tokens
markup_body = pp.originalTextFor(pp.nestedExpr('{', '}'))
italicized = ('ital' + markup_body).setParseAction(convert_markup_to_html("<I>", "</I>"))
bolded = ('bold' + markup_body).setParseAction(convert_markup_to_html("<B>", "</B>"))
# another markup and parse action to parse links - again using transform string
# to recursively parse any markup in the link text
def convert_link_to_html(s, l, t):
t['link_text'] = wiki_markup.transformString(t['link_text'])
return '<A href="{url}">{link_text}</A>'.format_map(t)
urlRef = ('link'
+ '{' + pp.SkipTo('->')('link_text') + '->' + pp.SkipTo('}')('url') + '}'
).setParseAction(convert_link_to_html)
# now inject all the markup bits as possible markup expressions
wiki_markup <<= urlRef | italicized | bolded
试试看!
wiki_input = """
Here is a simple Wiki input:
ital{This is in italics}.
bold{This is in bold}!
bold{This is in ital{bold italics}! But this is just bold.}
Here's a URL to link{Pyparsing's bold{Wiki Page}!->https://github.com/pyparsing/pyparsing/wiki}
"""
print(wiki_markup.transformString(wiki_input))
印刷:
Here is a simple Wiki input:
<I>This is in italics</I>.
<B>This is in bold</B>!
<B>This is in <I>bold italics</I>! But this is just bold.</B>
Here's a URL to <A href="https://github.com/pyparsing/pyparsing/wiki">Pyparsing's <B>Wiki Page</B>!</A>
鉴于您的标记示例,我认为这种方法可能会让您走得更远。
推荐阅读
- ms-word - 在 RMarkdown 中更改 Word 文档样式
- r - R - 将文件路径添加到数据帧的每一行
- java - Java 框架清晰度
- material-ui - Material-ui 组件中字体 Roboto 的不同变体
- python - python中的庞加莱距离
- extjs - ExtJS 6 在现代边缘选择器中使用 TPL
- go - 具有多个等待组的管道中通道范围内的死锁
- c++ - 窗口透明时是否可以接收 WM_TOUCH (WS_EX_TRANSPARENT)?
- angular - 仅使用 prerender.io 客户端预渲染 Angular 7 SPA
- javascript - 使用 javascript 生成随机彩色框