feat(#3251): Added object to

This commit is contained in:
maxonfjvipon 2024-07-19 15:16:24 +03:00
parent 091f0ed644
commit 0b0d4575c8
No known key found for this signature in database
GPG Key ID: D8563899D473D273
7 changed files with 464 additions and 4 deletions

View File

@ -25,4 +25,5 @@
# package name contains capital letter and such names are conventional.
---
exclude_paths:
- "eo-runtime/src/main/java/EOorg/EOeolang/EOtxt/EOsscanf.java"
- "eo-runtime/src/main/java/EOorg/EOeolang/EOtxt/EOregex$EOpattern$EOmatch$EOmatched_from_index.java"
- "eo-runtime/src/main/java/EOorg/EOeolang/EOtxt/EOregex$EOcompiled.java"

View File

@ -27,7 +27,7 @@ SOFTWARE.
<xsl:template match="/program/errors">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
<xsl:for-each select="//o[count(o[@name and not(@base) and not(@atom) and count(o)=0]) &gt; 4]">
<xsl:for-each select="//o[count(o[@name and not(@base) and not(@atom) and count(o)=0]) &gt; 5]">
<xsl:element name="error">
<xsl:attribute name="check">
<xsl:text>too-many-attributes</xsl:text>
@ -42,7 +42,7 @@ SOFTWARE.
<xsl:text>"</xsl:text>
<xsl:value-of select="@name"/>
<xsl:text>" </xsl:text>
<xsl:text>has more than four free attributes, it's too many</xsl:text>
<xsl:text>has more than five free attributes, it's too many</xsl:text>
</xsl:element>
</xsl:for-each>
</xsl:copy>

View File

@ -0,0 +1,109 @@
# The MIT License (MIT)
#
# Copyright (c) 2016-2024 Objectionary.com
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
+architect yegor256@gmail.com
+home https://github.com/objectionary/eo
+package org.eolang.txt
+rt jvm org.eolang:eo-runtime:0.0.0
+rt node eo2js-runtime:0.0.0
+version 0.0.0
# Regular expression in Perl format.
# Here `pattern` is a string pattern.
# It starts and ends with slash (e.g. "/(your-pattern)/"),
# Also it can be specified by the flag option,
# e.g.
# ```
# (`QQ.txt.regex "/(word)/i").compiled.matches "WORD"
# ```
# Supported flags:
# /d - Enables Unix lines mode.
# /i - Enables case-insensitive matching.
# /x - Permits whitespace and comments in pattern.
# /m - Enables multiline mode.
# /s - Enables dotall mode.
# /u - Enables Unicode-aware case folding.
[expression] > regex
compiled > @
# Compile regular expression into pattern.
[] > compiled /pattern
# Regular expression compiled into pattern.
# Here `serialized` is `bytes` which represents serialized structure in memory
# that is built after compilation.
[serialized] > pattern
(^.match txt).next.exists > [txt] > matches
# Creates a `matcher` that will match the given input against the pattern.
[txt] > match
(matched-from-index 1 0).matched > next
# Get `number`-th block matched from `start` position.
# If string subsequence is found - returns `matched` object,
# returns `not-matched` otherwise.
[number start] > matched-from-index /matched
# Block matched the pattern.
# Here:
# - `number` - sequence number of matched block,
# - `start` - matched region start index.
# If equals to -1 - block was not matched
# - `from` - index where matched string sequence starts
# - `to` - index where matched string sequence ends
# - `groups` - tuple of identified matched groups
#
# The block provides the next API to work with matched string subsequence:
# - `groups-count` - to get amount of matched groups
# - `exists` - to check if matched block is not emtpy
# - `next` - to get next matched block
# - `text` - to get matched subsequence as `string`
# - `group {index}` - to get string subsequence captured by `index`-th group.
[number start from to groups] > matched
$ > matched
groups.length > groups-count
start.gte 0 > exists
if. > next
exists
matched.
^.matched-from-index
number.plus 1
to
error "Matched block does not exist, can't get next"
if. > text
exists
group 0
error "Matched block does not exist, can't get text"
# Returns the string subsequence captured by the group
# by `index` during the `match` operation.
^.groups.at index > [index] > group
# Block which does not match the provided pattern.
# Decorates `matched` block with corresponding `error`s.
[number] > not-matched
^.matched > @
number
-1
error "Matched block does not exist, can't get 'from' position"
error "Matched block does not exist, can't get 'to' position"
error "Matched block does not exist, can't get groups"

View File

@ -0,0 +1,79 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2016-2024 Objectionary.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* @checkstyle PackageNameCheck (4 lines)
*/
package EOorg.EOeolang.EOtxt;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import org.eolang.Atom;
import org.eolang.Attr;
import org.eolang.Data;
import org.eolang.ExFailure;
import org.eolang.Param;
import org.eolang.PhDefault;
import org.eolang.Phi;
import org.eolang.XmirObject;
/**
* Regex.compiled.
* @since 0.39.0
* @checkstyle TypeNameCheck (5 lines)
*/
@XmirObject(oname = "regex.compiled")
public final class EOregex$EOcompiled extends PhDefault implements Atom {
@Override
public Phi lambda() throws Exception {
final Phi regex = this.take(Attr.RHO);
final String expression = new Param(regex, "expression").strong(String.class);
final StringBuilder builder = new StringBuilder();
if (!expression.startsWith("/")) {
throw new ExFailure("Wrong regex syntax: \"/\" is missing");
}
final int last = expression.lastIndexOf("/");
if (!expression.endsWith("/")) {
builder.append("(?").append(expression.substring(last + 1)).append(")");
}
builder.append(expression, 1, last);
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final ObjectOutputStream ous = new ObjectOutputStream(baos);
final Phi pattern = regex.take("pattern");
try {
final Pattern compiled = Pattern.compile(builder.toString());
ous.writeObject(compiled);
pattern.put(0, new Data.ToPhi(baos.toByteArray()));
ous.close();
return pattern;
} catch (final PatternSyntaxException exception) {
throw new ExFailure(
"Regular expression syntax is invalid",
exception
);
}
}
}

View File

@ -0,0 +1,97 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2016-2024 Objectionary.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
* @checkstyle PackageNameCheck (4 lines)
*/
package EOorg.EOeolang.EOtxt;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eolang.AtVoid;
import org.eolang.Atom;
import org.eolang.Attr;
import org.eolang.Data;
import org.eolang.Dataized;
import org.eolang.Param;
import org.eolang.PhDefault;
import org.eolang.Phi;
import org.eolang.XmirObject;
/**
* Regex.pattern.match.matched-from-index.
* @since 0.39.0
* @checkstyle TypeNameCheck (5 lines)
*/
@XmirObject(oname = "regex.pattern.match.matched-from-index")
public final class EOregex$EOpattern$EOmatch$EOmatched_from_index extends PhDefault
implements Atom {
/**
* Ctor.
*/
public EOregex$EOpattern$EOmatch$EOmatched_from_index() {
this.add("number", new AtVoid("number"));
this.add("start", new AtVoid("start"));
}
@Override
public Phi lambda() throws Exception {
final Phi match = this.take(Attr.RHO);
final InputStream bais = new ByteArrayInputStream(
new Dataized(match.take(Attr.RHO).take("serialized")).take()
);
final Matcher matcher = ((Pattern) new ObjectInputStream(bais).readObject()).matcher(
new Param(match, "txt").strong(String.class)
);
final Phi start = this.take("start");
final Long from = new Dataized(this.take("start")).take(Long.class);
final boolean found = matcher.find(Math.toIntExact(from));
final Phi result;
if (found) {
result = match.take("matched");
result.put("number", this.take("number"));
result.put("start", start);
result.put("from", new Data.ToPhi((long) matcher.start()));
result.put("to", new Data.ToPhi((long) matcher.end()));
final Phi[] groups;
if (matcher.groupCount() > 0) {
groups = new Phi[matcher.groupCount() + 1];
for (int idx = 0; idx < groups.length; ++idx) {
groups[idx] = new Data.ToPhi(matcher.group(idx));
System.out.printf("%d: %s\n", idx, matcher.group(idx));
}
} else {
groups = new Phi[] {new Data.ToPhi(matcher.group())};
}
result.put("groups", new Data.ToPhi(groups));
} else {
result = match.take("not-matched");
result.put("number", this.take("number"));
}
return result;
}
}

View File

@ -0,0 +1,174 @@
# The MIT License (MIT)
#
# Copyright (c) 2016-2024 Objectionary.com
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included
# in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
+alias org.eolang.txt.regex
+architect yegor256@gmail.com
+home https://github.com/objectionary/eo
+tests
+package org.eolang.txt
+version 0.0.0
# Test.
[] > matches-regex-against-the-pattern
(regex "/[a-z]+/").compiled.matches "hello" > @
# Test.
[] > does-not-matches-regex-against-the-pattern
((regex "/[a-z]+/").compiled.matches "123").not > @
# Test.
[] > matched-sequence-has-right-border-indexes
((regex "/[a-z]+/").match "!hello!").next > n
and. > @
0.eq n.start
and.
1.eq n.from
6.eq n.to
# Test.
[] > regex-returns-valid-matched-string-sequence
((regex "/[a-z]+/").match "!hello!").next.text.eq "hello" > @
# Test.
[] > regex-returns-valid-second-matched-block
((regex "/[a-z]+/").match "!hello!world!").next.next > second
and. > @
and.
and.
and.
second.text.eq "world"
second.number.eq 2
second.start.eq 6
second.from.eq 7
second.to.eq 12
# Test.
[] > throws-on-getting-next-on-not-matched-block
((regex "/[a-z]+/").match "123").next.next > @
# Test.
[] > throws-on-getting-from-position-on-not-matched-block
((regex "/[a-z]+/").match "123").next.from > @
# Test.
[] > throws-on-getting-to-position-on-not-matched-block
((regex "/[a-z]+/").match "123").next.to > @
# Test.
[] > throws-on-getting-groups-count-on-not-matched-block
((regex "/[a-z]+/").match "123").next.groups-count > @
# Test.
[] > throws-on-getting-groups-on-not-matched-block
((regex "/[a-z]+/").match "123").next.groups > @
# Test.
[] > throws-on-getting-specified-group-on-not-matched-block
((regex "/[a-z]+/").match "123").next.group 1 > @
# Test.
[] > throws-on-getting-text-on-not-matched-block
((regex "/[a-z]+/").match "123").next.text > @
# Test.
[] > regex-matches-dotall-option
regex
"/(.*)/s"
.compiled
.matches > @
"too \\n many \\n line \\n Feed\\n"
# Test.
[] > regex-matches-with-case-insensitive-option
regex
"/(string)/i"
.compiled
.matches > @
"StRiNg"
# Test.
[] > regex-matches-with-multiline-option
regex
"/(^([0-9]+).*)/m"
.compiled
.matches > @
"1 bottle of water on the wall. \\n1 bottle of water."
# Test.
[] > regex-matches-entire-pattern
regex
"/[0-9]/\\d+/"
.compiled
.matches > @
"2/75"
# Test.
[] > regex-matches-with-regex-unix-lines
regex
"/(.+)/d"
.compiled
.matches > @
"A\\r\\nB\\rC\\nD"
# Test.
[] > regex-matches-with-regex-case-insensitive-and-caps
regex
"/(word)/i"
.compiled
.matches > @
"WORD"
# Test.
[] > regex-ignores-comments-in-string
regex
"/(\\d) #ignore this comment/x"
.compiled
.matches > @
"4"
# Test.
[] > regex-matches-with-unicode-case-and-insensitive
regex
"/(yildirim)/ui"
.compiled
.matches > @
"Yıldırım"
# Test.
[] > throws-on-missing-first-slash-in-regex
(regex "(.)+").compiled > @
# Test.
[] > regex-contains-valid-groups-on-each-matched-block
((regex "/([a-z]+)([1-9]{1})/").compiled.match "!hello1!world2").next > first
first.next > second
and. > @
and.
and.
first.groups-count.eq 3
(first.group 1).eq "hello"
(first.group 2).eq "1"
and.
and.
second.groups-count.eq 3
(second.group 1).eq "world"
(second.group 2).eq "2"

View File

@ -121,7 +121,7 @@ final class SnippetTestCase {
.set("arguments", map.get("args"));
f.exec("clean", "test");
final String log = f.log();
Logger.info(this, log);
Logger.debug(this, log);
MatcherAssert.assertThat(
String.format("'%s' printed something wrong", yml),
log,