我需要在Java中快速构建一个非常简化版本的类似html的标记语言的解析器.在python中,我会使用pyparsing库来执行此操作.Java有类似的东西吗?请不要建议已经在那里进行html解析的库,我的应用程序是一个学校作业,它将演示走过一个对象树并使用访问者模式序列化为文本,所以我不会在这里考虑现实世界的术语.基本上我在这里需要的只是标签,属性和文本节点.
我希望能够从一段文字中提取字母的类型和数量,其中字母可以是任何顺序.还有一些其他的解析正在进行中,但这一点让我难过!
input -> result
"abc" -> [['a',1], ['b',1],['c',1]]
"bbbc" -> [['b',3],['c',1]]
"cccaa" -> [['a',2],['c',3]]
Run Code Online (Sandbox Code Playgroud)
我可以使用搜索或扫描并重复每个可能的字母,但有一个干净的方式吗?
这是我得到的:
from pyparsing import *
def handleStuff(string, location, tokens):
return [tokens[0][0], len(tokens[0])]
stype = Word("abc").setParseAction(handleStuff)
section = ZeroOrMore(stype("stype"))
print section.parseString("abc").dump()
print section.parseString("aabcc").dump()
print section.parseString("bbaaa").dump()
Run Code Online (Sandbox Code Playgroud) 我有这样的字符串:
"MSE 2110, 3030, 4102"
Run Code Online (Sandbox Code Playgroud)
我想输出:
[("MSE", 2110), ("MSE", 3030), ("MSE", 4102)]
Run Code Online (Sandbox Code Playgroud)
这是我的方式,虽然我还没有完成它:
def makeCourseList(str, location, tokens):
print "before: %s" % tokens
for index, course_number in enumerate(tokens[1:]):
tokens[index + 1] = (tokens[0][0], course_number)
print "after: %s" % tokens
course = Group(DEPT_CODE + COURSE_NUMBER) # .setResultsName("Course")
course_data = (course + ZeroOrMore(Suppress(',') + COURSE_NUMBER)).setParseAction(makeCourseList)
Run Code Online (Sandbox Code Playgroud)
这输出:
>>> course.parseString("CS 2110")
([(['CS', 2110], {})], {})
>>> course_data.parseString("CS 2110, 4301, 2123, 1110")
before: [['CS', 2110], 4301, 2123, 1110]
after: [['CS', 2110], ('CS', 4301), ('CS', 2123), ('CS', …Run Code Online (Sandbox Code Playgroud) 我正在使用pyparser来处理hex-to-text转换器的输出.它每行打印16个字符,用空格分隔.如果十六进制值是ASCII可打印字符,则打印该字符,否则转换器输出句点(.)
大多数输出看起来像这样:
. a . v a l i d . s t r i n g .
. a n o t h e r . s t r i n g .
. e t c . . . . . . . . . . . .
Run Code Online (Sandbox Code Playgroud)
我描述这一行的pyparsing代码是:
dump_line = 16 * Word(printables, exact=1)
Run Code Online (Sandbox Code Playgroud)
这很好,直到十六进制文本转换器达到十六进制值0x20,这导致它输出一个空格.
l i n e . w . a . s p a c e .
Run Code Online (Sandbox Code Playgroud)
在这种情况下,pyparsing忽略输出的空间并从下一行中取出字符以产生16个字符的"配额".
有人可以建议我如何告诉pyparsing期望16个字符,每个字符用空格分隔,其中空格也可以是有效字符?
提前致谢.Ĵ
grammar = Literal("from") + Literal(":") + Word(alphas)
Run Code Online (Sandbox Code Playgroud)
语法需要拒绝from : mary并且只接受from:mary即没有任何交错空间.如何在pyparsing中强制执行此操作?谢谢
AKA"将从Parser.parseAction的结果构造的子节点添加到父解析树"
我正在尝试使用PyParsing(规则恕我直言)解析PHP文件,其中函数定义已使用JavaDoc样式注释进行注释.原因是我想以一种可用于生成客户端存根代码的方式存储类型信息.
例如:
/*
* @vo{$user=UserAccount}
*/
public function blah($user){ ......
Run Code Online (Sandbox Code Playgroud)
现在,我已经能够编写一个解析器,使用PyParser非常容易.但是,PyParser带有一个内置的javaStyleComment Token,我想重用它.所以我解析了代码,然后尝试附加一个parseAction,它将剥离gunk并运行一个子解析器(抱歉,不确定术语)并将结果附加到父解析树.
我无法弄清楚该怎么做.代码附在下面.顺便说一句,我可以轻松编写自己的javaStyleComment,但我想知道一般是否可以链接解析结果?
再次,抱歉,如果我的问题不简洁,我只是这个东西的新手.
#@PydevCodeAnalysisIgnore
from pyparsing import delimitedList,Literal,Keyword,Regex,ZeroOrMore,Suppress,Optional,QuotedString,Word,hexnums,alphas,\
dblQuotedString,FollowedBy, sglQuotedString,oneOf,Group
import pyparsing
digits = "0123456789"
colon = Literal(':')
semi = Literal(';')
period = Literal('.')
comma = Literal(',')
lparen = Literal('{')
rparen = Literal('}')
lbracket = Literal('(')
rbracket = Literal(')')
number = Word(digits)
hexint = Word(hexnums,exact=2)
text = Word(alphas)
php = Literal("<?php") + Literal("echo") + Literal("?>")
print php.parseString("""<?php echo ?>""")
funcPerm = oneOf("public private protected")
print funcPerm.parseString("""public""")
print funcPerm.parseString("""private""") …Run Code Online (Sandbox Code Playgroud) 我是新用的pyparsing,但我找不到如何解决这个相当容易的问题.我(目前)有一个简单的语法,但我找不到根据我在语法中定义的类型来区分解析结果的方法.
也许通过一个例子来解释它可能更容易.假设这个元素:
elem = foo | bar
Run Code Online (Sandbox Code Playgroud)
当我调用时:
elem.parseString("...")
Run Code Online (Sandbox Code Playgroud)
假设字符串与我的语法匹配,我如何区分它是否与'foo'或'bar'匹配?我得到了ParseResults的实例对象,没有这样的元数据.
提前致谢.
我正在使用PyParsing来解析一些类似C格式的大文本文件(大括号和分号以及所有这些).
PyParsing效果很好,但由于我的文件大小,它很慢并且消耗了大量内存.
因此,我想尝试实现一种增量解析方法,其中我将逐个解析源文件的顶级元素.scanStringpyparsing 的方法似乎是明显的方法.但是,我想确保在解析的部分之间没有无效/不可解析的文本scanString,并且无法找到执行此操作的好方法.
这是一个简化的例子,显示了我遇到的问题:
sample="""f1(1,2,3); f2_no_args( );
# comment out: foo(4,5,6);
bar(7,8);
this should be an error;
baz(9,10);
"""
from pyparsing import *
COMMENT=Suppress('#' + restOfLine())
SEMI,COMMA,LPAREN,RPAREN = map(Suppress,';,()')
ident = Word(alphas, alphanums+"_")
integer = Word(nums+"+-",nums)
statement = ident("fn") + LPAREN + Group(Optional(delimitedList(integer)))("arguments") + RPAREN + SEMI
p = statement.ignore(COMMENT)
for res, start, end in p.scanString(sample):
print "***** (%d,%d)" % (start, end)
print res.dump()
Run Code Online (Sandbox Code Playgroud)
输出:
***** (0,10)
['f1', ['1', '2', '3']] …Run Code Online (Sandbox Code Playgroud) 我试图在我的Windows机器上编译Pyparsing但是遇到以下错误:
python setup.py build_ext --inplace
running build_ext
cythoning pyparsing.pyx to pyparsing.c
Error compiling Cython file:
------------------------------------------------------------
...
If C{include} is set to true, the matched expression is also parsed (the
skipped text
and matched expression are returned as a 2-element list). The C{ignore}
argument is used to define grammars (typically quoted strings and comment
s) that
might contain false matches.
"""
def __init__( self, other, include=False, ignore=None, failOn=None ):
^
------------------------------------------------------------
pyparsing.pyx:2764:31: Expected an identifier, found 'include'
Error compiling Cython …Run Code Online (Sandbox Code Playgroud) 我试图使用pyparsing来解析机器人框架,这是一个基于文本的DSL.sytnax就像跟随(抱歉,但我认为在BNF中描述它有点困难).机器人框架中的单行可能如下所示:
Library\tSSHClient with name\tnode
Run Code Online (Sandbox Code Playgroud)
\ t是标签,在机器人框架中,它被透明地转移到2""(事实上,它只是调用str.replace('\ t','')来替换标签,但它会修改每个标签的实际长度line,len('\ t')为1但len('')为2.).在机器人中,使用2个或更多的空格和'\ t'来分割标记,如果单词之间只有1个空格,则这些单词被认为是标记组.
Library\tSSHClient with name\tnode
Run Code Online (Sandbox Code Playgroud)
如果正确解析,实际上会拆分为以下标记:
['Library', 'SSHClient', 'with name', 'node']
Run Code Online (Sandbox Code Playgroud)
由于"with"和"name"之间只有1个空格,因此解析器认为它属于组语法标记.
这是我的代码:
ParserElement.setDefaultWhitespaceChars('\r\n\t ')
source = "Library\tSSHClient with name\tnode"
EACH_LINE = Optional(Word(" ")).leaveWhitespace().suppress() + \
CaselessKeyword("library").suppress() + \
OneOrMore((Word(alphas)) + White(max=1).setResultName('myValue')) +\
SkipTo(LineEnd())
res = EACH_LINE.parseString(source)
print res.myValue
Run Code Online (Sandbox Code Playgroud)
问题:
1)我已经设置了WhiteSpaces,如果我想要完全匹配2个或更多Whitespaces或一个或多个Tab,我认为代码需要:White(ws ='',min = 2)| 白色(ws ='\ t',min = 1)但这会失败,所以我无法指定空白值?
2)有没有办法获得匹配的结果索引?我尝试了setParseAction,但似乎我无法通过此回调获取索引.我需要开始和结束索引来突出显示单词.
3)LineStart和LineEnd是什么意思?我打印这些值,似乎它们只是正常的字符串,我是否必须在一行前面写一些东西,如:LineStart()+ balabala ... + LineEnd()?
但是,谢谢,我有一个限制,我无法将'\ t'替换为'''
from pyparsing import *
source = "Library\tsshclient\t\t\twith name s1"
value = Combine(OneOrMore(Word(printables) | White(' ', max=1) …Run Code Online (Sandbox Code Playgroud)