gpt4 book ai didi

xml - raku 语法的标记不会命中文档的第一次出现,但会命中类似的后续出现

转载 作者:行者123 更新时间:2023-12-03 18:20:33 28 4
gpt4 key购买 nike

我想用希伯来语处理整个 Tanach 文件。为此,我选择了 Raku 语言,因为它的一些特性(语法和 unicode 支持)。
因此,我定义了一些标记来选择相关数据。

grammar HEB {
token TOP {'<hebrewname>'<t_word>'</hebrewname>'}
token t_word {<graph>+}
};

grammar CHA {
token TOP {'<c n="'<t_number>'">'}
token t_number {\d+}
};

grammar VER {
token TOP {'<v n="'<t_number>'">'}
token t_number {\d+}
};

grammar WOR {
token TOP {'<w>'<t_word>'</w>'}
token t_word {<graph>+}
};
在这里,文档的一小部分(XML 格式的 Tanach)足以说明问题: <names> <name>Genesis</name> <abbrev>Gen</abbrev> <number>1</number> <filename>Genesis</filename> <hebrewname>בראשית</hebrewname> </names> <c n="1"> <v n="1"> <w>בְּ/רֵאשִׁ֖ית</w> <w>בָּרָ֣א</w> <w>אֱלֹהִ֑ים</w> <w>אֵ֥ת</w> <w>הַ/שָּׁמַ֖יִם</w> <w>וְ/אֵ֥ת</w> <w>הָ/אָֽרֶץ׃</w> </v> <v n="2"> <w>וְ/הָ/אָ֗רֶץ</w> <w>הָיְתָ֥ה</w> <w>תֹ֙הוּ֙</w> <w>וָ/בֹ֔הוּ</w> <w>וְ/חֹ֖שֶׁךְ</w> <w>עַל־</w> <w>פְּנֵ֣י</w> <w>תְה֑וֹם</w> <w>וְ/ר֣וּחַ</w> <w>אֱלֹהִ֔ים</w> <w>מְרַחֶ֖פֶת</w> <w>עַל־</w> <w>פְּנֵ֥י</w> <w>הַ/מָּֽיִם׃</w> </v>问题是代码无法识别 二首单词( <w>בְּ/רֵאשִׁ֖ית</w> <w>בָּרָ֣א</w> )但似乎可以很好地处理以下单词...
有人可以向我解释什么是错的?
主循环是:
for $file_in.lines -> $line {
$memline = $line.trim;

if HEB.parse($memline) {
say "hebrew name of book is "~ $/<t_word>;
next;
}
if CHA.parse($memline) {
say "chapitre number is "~ $/<t_number>;
next;
}
if VER.parse($memline) {
say "verse number is "~ $/<t_number>;
next;
}
if WOR.parse($memline) {
$computed_word_value = 0;
say "word is "~ $/<t_word>;
$file_out.print("$/<t_word>");
say "numbers of graphemes of word is "~ $/<t_word>.chars;
@exploded_word = $/<t_word>.comb;
for @exploded_word {
say $_.uniname;
};
next;
}
say "not processed";
}
输出文件 :
请注意在 之后经文编号为 1 ,不处理前 2 个单词。不要专注于扭曲的希伯来语(Windows 控制台)!
not processed
not processed
not processed
not processed
not processed
hebrew name of book is ׳‘׳¨׳׳©׳™׳×
not processed
chapitre number is 1
verse number is 1
not processed
not processed
word is ׳ײ±׳œײ¹׳”ײ´ײ‘׳™׳
numbers of graphemes of word is 5
HEBREW LETTER ALEF
HEBREW LETTER LAMED
HEBREW LETTER HE
HEBREW LETTER YOD
HEBREW LETTER FINAL MEM
word is ׳ײµײ¥׳×
numbers of graphemes of word is 2
HEBREW LETTER ALEF
HEBREW LETTER TAV
not processed
word is ׳•ײ°/׳ײµײ¥׳×
numbers of graphemes of word is 4
HEBREW LETTER VAV
SOLIDUS
我希望我的问题清楚地暴露出来。

最佳答案

我无法重现你的问题。
我唯一能猜到的是你没有用正确的编码打开文件。
或者更糟的是,您从 STDIN 获取文件并且没有选择正确的代码页。 (这是有道理的,因为您的输出也是 mojibake。)
Rakudo 并没有真正做代码页,所以如果你不把你的环境设置为 utf8 你必须改变 $*STDIN 的编码(和 $*STDOUT )匹配任何内容。

我现在要假装你在 CodeReview.StackExchange.com 上发帖了。
首先我不知道你为什么要为这么小的东西创建一个完整的语法,这可以用简单的正则表达式轻松完成。

my token HEB {
'<hebrewname>'
$<t_word> = [<.graph>+]
'</hebrewname>'
}
my token CHA {
'<c n="' $<t_number> = [\d+] '">'
}
my token VER {
'<v n="' $<t_number> = [\d+] '">'
}
my token WOR {
'<w>' $<t_word> = [<.graph>+] '</w>'
}
老实说,这仍然比您似乎需要的要多,因为您每个正则表达式只处理一个元素。
这也忽略了我真的不喜欢你给元素命名 t_wordt_number .这是毫无意义的,因为它们在 $/ 内, 而且 Grammar 也没有任何类似命名的方法,因此它们不可能干扰任何其他命名空间。如果你必须给他们起名字,就给他们起描述性的名字。
您可以限制 $/仅将字符串化为您关心的部分 <(…)> . (它在这里有效,因为您只捕获一件事。) <(表示忽略之前的所有内容,以及 )>意味着忽略之后的一切。
my token HEB {
'<hebrewname>'
<( <.graph>+ )> # $/ will contain only what <.graph>+ matches
'</hebrewname>'
}
my token CHA {
'<c n="' <( \d+ )> '">'
}
my token VER {
'<v n="' <( \d+ )> '">'
}
my token WOR {
'<w>' <( <.graph>+ )> '</w>'
}

您正在解析它,好像它只是一个面向行的文件。
这确实有一定的意义,因为它被格式化为一个,这会导致更少的内存使用。
为此使用命名的正则表达式,更不用说整个语法有点矫枉过正了。当这种简单的匹配不是真的需要时,它还可以分离逻辑。
以下是我将如何以面向行的方式解析该文件:
my $in-names = False;
my %names;
my @chapters;
my @verses;
my @current-verse;

for $file_in.lines {
when /'<names>' / { $in-names = True }
when /'</names>'/ { $in-names = False }

# chapter
when /'<c n="' <( \d+ )> '">'/ {
@verses := @chapters[ +$/ - 1 ] //= [];
}
when /'</c>'/ {
# finalize this chapter
# for example print out statistics
# (only needed if you don't want `default` to catch it)
}

# verse
when /'<v n="' <( \d+ )> '">'/ {
@current-verse := @verses[ +$/ - 1 ] //= [];
}
when /'</v>'/ {
# finalize this verse
}

# word
when /'<w>' <( <.graph>+ )> '</w>'/ {
push @current-verse, ~$/;
}

# name tags
# must be after more specific regexes
when /'<' <tag=.ident> '>' $<value> = [<.ident>|\d+] {} "</$<tag>>"/ {
if $in-names {
%names{~$<tag>} = ~$<value>
} else {
note "not handling $<tag> => $<value> outside of <names>"
}
}

default { note "unexpected text '$_'" }
}
请注意 when使您不必这样做 next .
因为我们只使用 $_而不是 $line ,这使得我们可以直接使用正则表达式作为那些 when 的条件声明。
我懒得用 ^$所以没有必要 trim或使用 ^\s*\s*$ .
它确实使它变得更加脆弱,因此如果出现问题,您可能需要更改它。
如果你真的只想像你正在做的那样做简单的线处理,我相信你可以改变上面的内容以满足你的需要。
我想让这对将来遇到这个问题的人更有用。所以我从文件中创建了一个数据结构,而不是按照你在做什么。

真的,如果我要去 .parse(),我可能只会达到语法。一次完成整个文件。
这就是这样一个语法的样子。

grammar Book {
rule TOP {
<names>
<chapter> +
# note that there needs to be a space between <chapter> and +
# so that whitespace can be between <c…>…</c> elements
}

rule names {
'<names>' ~ '</names>'
<name> +
}

token name {
'<' <tag=.ident> '>'
$<name> = [<.ident>|\d+]
{}
"</$<tag>>"
}

rule chapter {
# note space before ]
['<c n="' <number> '">' ] ~ '</c>'
<verse> +
}
rule verse {
['<v n="' <number> '">' ] ~ '</v>'
<word> +
}

token number { \d+ }
token word { '<w>' <( <.graph>+ )> '</w>' }
}
像你一样做类似的处理
class Line-Actions {
has IO::Handle:D $.file-out is required;
has $!number-type is default<chapter>;

method name ($/) {
if $<tag> eq 'hebrewname' {
say "hebrew name of book is $<name>";
}
}

# note that .chapter and .verse will run at the end
# of parsing them, which is too late for when .word is processed
# so we do it in .number instead
method number ($/) {
say "$!number-type number is $/";
$!number-type = 'verse';
}
method chapter ($/) {
# reset to default of "chapter"
# as the next .number will be for the next chapter
$!number-type = Nil;
}

method word ($/) {
say "word is $/";
$!file-out.print(~$/);
say "number of graphemes in word is $/.chars()";
.say for "$/".comb.map: *.uninames.join(', ');
}
}


Book.parsefile(
$filename,
actions => Line-Actions.new( 'outfile.txt'.IO.open(:w) )
);

关于xml - raku 语法的标记不会命中文档的第一次出现,但会命中类似的后续出现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66266790/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com