简单标签解析器


9

这是宽容HTML解析器的模型。在此代码中,代替解析HTML和提取属性,标记解析器将很简单。

编写一个解析标记结构并返回其括号形式的函数。开头标签由一个小写字母组成,结束标签由一个大写字母组成。例如,aAbaAB解析为(a)(b(a))或以HTML形式解析<a></a><b><a></a></b>。当然,标签可以并列和嵌套。

必须处理“过早”的关闭标签。例如,在中abcAA闭合最外面a,因此将其解析为(a(b(c)))

多余的结束标记将被忽略:aAB解析为(a)

不处理重叠的标签。例如,根据先前的额外结束标记(-> ()+ (extra))abAB解析为(a(b)),而不是。(a(b))(b)abABabA(a(b))B

假设输入中没有空格和其他非法字符。

您无权使用任何库。

这是参考实现和测试用例列表:

#!/usr/bin/python

def pars(inpu):
  outp = ""
  stac = []
  i = 0
  for x in inpu:
    lowr = x.lower()
    if x == lowr:
      stac.append(x)
      outp += "(" + x
      i = i + 1
    else:
      while len(stac) > 1 and stac[len(stac) - 1] != lowr:
        outp += ")"
        stac.pop()
        i = i - 1
      if len(stac) > 0:
        outp += ")"
        stac.pop()
        i = i - 1
  outp += ")" * i
  return outp

tests = [
  ("aAaAbB", "(a)(a)(b)"),
  ("abBcdDCA", "(a(b)(c(d)))"),
  ("bisSsIB", "(b(i(s)(s)))"),
  ("aAabc", "(a)(a(b(c)))"),
  ("abcdDA", "(a(b(c(d))))"),
  ("abcAaA", "(a(b(c)))(a)"),
  ("acAC", "(a(c))"),
  ("ABCDEFG", ""),
  ("AbcBCabA", "(b(c))(a(b))")
]

for case, expe in tests:
  actu = pars(case)
  print "%s: C: [%s] E: [%s] A: [%s]" % (["FAIL", "PASS"][expe == actu], case, expe, actu)

最短的代码胜出。


像其他任何代码高尔夫球一样,允许使用标准库
Ming-Tang

在长度,也没有嵌套层次没有限制
明腾

4
你应该输入该线索与关闭标签,如添加测试用例AbcBCabA(应解析为(b(c))(a(b))我的代码可能是除了这种情况下更短。
MtnViewMark

Answers:


1

Golfscript,54个字符

{[]:|\{.96>{.|+:|;40\}{32+|?).')'*\|>:|;}if}%|,')'*}:$

测验

;["aAaAbB" "abBcdDCA" "bisSsIB" "aAabc" "abcdDA" "abcAaA" "acAC" "aAB" "abAB" "AbcBCabA"]{.' '\$n}%

aAaAbBaAaAbB (a)(a)(b)
abBcdDCA (a(b)(c(d)))
bisSsIB (b(i(s)(s)))
aAabc (a)(a(b(c)))
abcdDA (a(b(c(d))))
abcAaA (a(b(c)))(a)
acAC (a(c))
aAB (a)
abAB (a(b))
AbcBCabA (b(c))(a(b))

6

Haskell,111个字符

s@(d:z)§c|c>'^'=toEnum(fromEnum c-32):s++'(':[c]|d<'='=s|d==c=z++")"|1<3=(z++")")§c
p=tail.foldl(§)"$".(++"$")

这是Haskell的漂亮高尔夫。有趣的功能:堆栈和累加输出保持在同一字符串中!

测试用例:

> runTests 
Pass: aAbaAB parsed correctly as (a)(b(a))
Pass: abcA parsed correctly as (a(b(c)))
Pass: aAB parsed correctly as (a)
Pass: abAB parsed correctly as (a(b))
Pass: aAaAbB parsed correctly as (a)(a)(b)
Pass: abBcdDCA parsed correctly as (a(b)(c(d)))
Pass: bisSsIB parsed correctly as (b(i(s)(s)))
Pass: aAabc parsed correctly as (a)(a(b(c)))
Pass: abcdDA parsed correctly as (a(b(c(d))))
Pass: abcAaA parsed correctly as (a(b(c)))(a)
Pass: acAC parsed correctly as (a(c))
Pass: AbcBCabA parsed correctly as (b(c))(a(b))

  • 编辑:(113→111)使用了@FUZxxl建议的模式

为d:z使用@模式可能会节省两个字符。
FUZxxl 2011年

4

适用于TI-83 +的Z80机器代码,41字节

这是在TI-83 +上运行的z80 cpu的十六进制机器代码实现。

11XXXX131AFE61380F6FE53E28CD9DB47DCD9DB4188EE1BDC03E29CD9DB4189BEF4504E5214CE1C9

XXXX(包括3-6)是您要解析的字符串的16位地址,减去1个字节。

以Z80-ASCII编码:

¹XX≤¯•⟙8𝑭o↥>(ˣïÑ}ˣïÑ≠á↑γ∊>)ˣïÑ≠Ì⬆︎E𝑤↥!₄L↑Φ

(大约,因为TI计算器有自己的字符集。)

请注意,以上未AsmPrgm包含


2

Windows PowerShell中,142 146 147 152 156 169

{$s=''
-join([char[]]"$args "|%{if(90-ge$_){')'*(($x=$s.indexOf("$_".ToLower())+1)+$s.Length*!$x)
$s=$s.substring($x)}else{"($_"
$s="$_$s"}})}

注意事项:这只是一个脚本块。如有必要,可以将其分配给变量或给定函数名称。您也可以通过将其放在前面.&后面,并将参数放在最后来运行它。使用最后一个空格终止未关闭的标签。

通过所有测试。测试脚本:

$tests = ("aAaAbB","(a)(a)(b)"),("abBcdDCA","(a(b)(c(d)))"),("bisSsIB","(b(i(s)(s)))"),("aAabc","(a)(a(b(c)))"),("abcdDA","(a(b(c(d))))"),("abcAaA", "(a(b(c)))(a)"),("acAC","(a(c))")
"function f " + ((gc ./tags.ps1)-join"`n") | iex
$tests | %{
    $result = f $_[0]
    ("FAIL: $($_[0]):$($_[1]) - $result", 'PASS')[$result -ceq $_[1]]
}

2

蟒- 114 113 153 192 174 159个字符

from sys import *
s="";c=a=argv[1]
for f in a:
 o=c.find;p=f.lower
 if '@'<f<'\\':
\td=o(f)-o(p())
\ts+=")"*d
\tc=(c[:o(p())]+c[o(f)+1:])
 else:s+=("("+f)
print s

滥用python的缩进解析器为完整选项卡使用一个空格,为两个选项卡使用五个空格。

编辑1-在range()函数中保存了不需要的空间

编辑2-修复了处理不正确的语法分析,未终止标记的问题。

编辑3-修正了一个错误,该错误可能导致标记树中的歧义生成“错误的”解析。实现了基于堆栈的策略,而不是计数器。

编辑4-将s.find重命名为o以防止保存用于重复调用的字符。f.lower也做同样的事情。

编辑5-添加了空格/制表符hack,节省了三个字符。

编辑6-放弃循环,转而使用“)” * d。


1
代替ord(f)...您可以使用'@'<f<'\\'如果您不需要检查,'\\'可以']'代替使用
gnibbler

1
您可以使用单个标签,而不要使用5个空格。SO代码标记虽然不能解决问题:(.。在您的情况下,只需将换行符和空格全部if ...:s+=")";c-=1else:s+="("+f;c+=1
排除在外即可

1
for i in range(d):s+=")"可以重写为s+=")"*d。您有174个字符。
cemper93 2011年

@cemper-好一点。我整天都做“ _” * 80,打高尔夫球时却忘了它。...另外,感谢@gnibbler的建议!
2011年

其实,我的意思是,你已经有了174个字符之前。所以你现在是159岁。
cemper93 2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.