In the documentation of Grammars under Section :
"Always succeed" assertion
I reproduced the example presented there, with added code to show the table produced, in each stage of the parsing mechanism :
use v6.d;
grammar Digifier {
rule TOP { [ <.succ> <digit>+ ]+ }
token succ { <?> }
token digit { <[0..9]> }
}
class Letters {
has #!numbers;
method digit ($/) { #!numbers.tail ~= <a b c d e f g h i j>[$/]; say '---> ' ~ #!numbers }
method succ ($/) { #!numbers.push: '!'; say #!numbers }
method TOP ($/) { make #!numbers[^(*-1)] }
}
say 'FINAL ====> ' ~ Digifier.parse('123 456 789', actions => Letters.new).made;
The result is the following:
[!]
---> !b
---> !bc
---> !bcd
[!bcd !]
---> !bcd !e
---> !bcd !ef
---> !bcd !efg
[!bcd !efg !]
---> !bcd !efg !h
---> !bcd !efg !hi
---> !bcd !efg !hij
[!bcd !efg !hij !]
FINAL ====> !bcd !efg !hij
I expected only 3 pushes in table #!numbers but I got 4.
I am puzzled about the need for an exclusion of the last value of table #!numbers in method "TOP".
Yes I know that the code produces the correct result but why?
Where does the last "Always Succeed" assertion come from?
A quantified group, eg [ A B ]+, is effectively a loop, repeatedly attempting to match A, and iff that matches, attempting to match B.
Unless it's an infinite loop -- in which case your program will hang -- it will eventually match N times and then move on. If A always matches, but your program doesn't hang, then that must mean B eventually failed. If so, A is guaranteed to have matched one more time than B.
In your code, A is <.succ> which reduces to <?>, which always matches. There are 4 attempts and thus A matches 4 times. In contrast B, which is <digit>+, fails on the fourth attempt so only matches 3 times.
Related
I come across below generic function which takes two Either type and a function as an argument. If both arguments are Either.Right then apply the function over it and returns the result, if any of the argument is Either.Left it returns NonEmptyList(Either.Left). Basically it performs the independent operation and accumulates the errors.
fun <T, E, A, B> constructFromParts(a: Either<E, A>, b: Either<E, B>, fn: (Tuple2<A, B>) -> T): Either<Nel<E>, T> {
val va = Validated.fromEither(a).toValidatedNel()
val vb = Validated.fromEither(b).toValidatedNel()
return Validated.applicative<Nel<E>>(NonEmptyList.semigroup()).map(va, vb, fn).fix().toEither()
}
val error1:Either<String, Int> = "error 1".left()
val error2:Either<String, Int> = "error 2".left()
val valid:Either<Nel<String>, Int> = constructFromParts(
error1,
error2
){(a, b) -> a+b}
fun main() {
when(valid){
is Either.Right -> println(valid.b)
is Either.Left -> println(valid.a.all)
}
}
Above code prints
[error 1, error 2]
Inside the function, it converts Either to ValidatedNel type and accumulates both errors
( Invalid(e=NonEmptyList(all=[error 1])) Invalid(e=NonEmptyList(all=[error 2])) )
My question is how it performs this operation or could anyone explain the below line from the code.
return Validated.applicative<Nel<E>>(NonEmptyList.semigroup()).map(va, vb, fn).fix().toEither()
Let's say I have a similar data type to Validated called ValRes
sealed class ValRes<out E, out A> {
data class Valid<A>(val a: A) : ValRes<Nothing, A>()
data class Invalid<E>(val e: E) : ValRes<E, Nothing>()
}
If I have two values of type ValRes and I want to combine them accumulating the errors I could write a function like this:
fun <E, A, B> tupled(
a: ValRes<E, A>,
b: ValRes<E, B>,
combine: (E, E) -> E
): ValRes<E, Pair<A, B>> =
if (a is Valid && b is Valid) valid(Pair(a.a, b.a))
else if (a is Invalid && b is Invalid) invalid(combine(a.e, b.e))
else if (a is Invalid) invalid(a.e)
else if (b is Invalid) invalid(b.e)
else throw IllegalStateException("This is impossible")
if both values are Valid I build a pair of the two values
if one of them is invalid, I get a new Invalid instance with the single value
if both are invalid, I use the combine function to build Invalid instance containing both values.
Usage:
tupled(
validateEmail("stojan"), //invalid
validateName(null) //invalid
) { e1, e2 -> "$e1, $e2" }
This works in a generic way, independent of the types E, A and B. But it only works for two values. We could build such a function for N values of type ValRes.
Now back to arrow:
Validated.applicative<Nel<E>>(NonEmptyList.semigroup()).map(va, vb, fn).fix().toEither()
tupled is similar to map (with hardcoded success function). va and vb here are similar to a and b in my example. Instead of returning a pair of values, here we have a custom function (fn) that combines the two values in case of success.
Combining the errors:
interface Semigroup<A> {
/**
* Combine two [A] values.
*/
fun A.combine(b: A): A
}
Semigroup in arrow is a way for combining two values from the same type in a single value of that same type. Similar to my combine function. NonEmptyList.semigroup() is the implementation of Semigroup for NonEmptyList that given two lists adds the elements together into a single NonEmptyList.
To sum up:
If both values are Valid -> it will combine them using the supplied function
If one value is Valid and one Invalid -> gives back the error
If both values are Invalid -> Uses the Semigroup instance for Nel to combine the errors
Under the hood this scales for 2 up to X values (22 I believe).
I want to check if a key exists in the first element(object) of the array.
When I write the following:
flowVars.payloadStored[0].data!=null
inside the when condition of choice, I am getting the following error:
Execution of the expression 'flowVars.payloadStored[0].data!=null' failed. -> [Error: null pointer: flowVars.payloadStored[0].data],[Near : {... flowVars.payloadStored[0].data ....}], ^,[Line: 1, Column: 1] -> ",
Even when trying
flowVars.payloadStored[0].['data']!=null
I am still getting an error:
[Error: unterminated string literal],[Near : {... flowVars.payloadStored[0].['data']!=null ....}], ^,[Line: 1, Column: 35]"
Any clues, how to do that?
It is tempting to do all mapping in one line but in reality you are doing chain of references. You should be sure that each link in the chain does exist.
Based on the message I guess that payloadStored may not exist or it is not an array or it has no elements in the array. To refer first element in the array you should be sure all is true. So, right DW transformation is not elegant but bulletproof should look like this to be sure you will not have null pointer exception:
%dw 1.0
%output application/json
---
{
data: flowVars.payloadStored[0].['data']
} when flowVars.payloadStored is :array and sizeOf (flowVars.payloadStored) > 0
otherwise
{
data: "Not Available"
}
So your logic should look like this:
flowVars.payloadStored is :array and sizeOf (flowVars.payloadStored) > 0 and flowVars.payloadStored[0].['data']!=null
Example is here https://simpleflatservice.com/mule4/DoubleAndTripleCheckTheInput.html
I'm playing with Map and I get a result I don't understand.
First, I construct the Map. No big whoop:
> my $m = Map.new: '1' => :1st, '2' => :2nd;
Map.new(("1" => :st(1),"2" => :nd(2)))
I access a single element by the literal key and get back a Pair:
> $m<1>.^name
Pair
> $m<<1>>.^name
Pair
That's all fine.
If I try it with the key in a variable, I get back a List instead:
> my $n = 1
1
> $m<<$n>>.^name
List
That list has the right value, but why do I get a List in that case and not the $m<<1>> case?
And, once I have the list, I seem unable to chain another subscript to it:
> $m<<$n>>.[0]
===SORRY!=== Error while compiling:
Unable to parse quote-words subscript; couldn't find right double-angle quote
at line 2
When you access an associative value like this, the compiler can tell that it need only ever return one value.
$m< 1 >
$m<< 1 >>
In Perl 6, a singular value will in many cases behave just like a list of one value.
42.elems == 1 # True
42.[0] =:= 42 # True
In the following case, the compiler can't immediately tell that it will only produce one value:
my $n = 1;
$m<< $n >>;
As it could produce 2 values:
my $o = '1 2';
$m<< $o >>;
If you want the string to be a single key, you have to use quotation marks.
$m<< "$o" >>
Or use the more appropriate {}
$m{ $n }
The $m<1> is just a combination of two features.
Quotewords: ( qw<> and qqww<<>> )
< a b c > eqv ("a", "b", "c")
< "a b" c > eqv (「"a」, 「b"」, "c") # three strings
<< a b c >> eqv ("a", "b", "c")
<< "a b" c >> eqv ("a b", "c") # two strings
Associative indexing:
%h< a b c > eqv %h{ < a b c > }
%h<< "a b" c >> eqv %h{ << "a b" c >> }
Also I now get back different values.
$m< 1 >.WHAT =:= Pair
$m<< 1 >>.WHAT =:= Pair
$m<< $n >>.WHAT =:= Pair # different
$m<< $o >>.WHAT =:= List
The reason $m<<$n>>.[0] doesn't work is the compiler thinks you are using a hyper postfix >>.[0].
There are a couple ways of working around that.
Actually using a hyper postfix
$m<<$n>>>>.[0]
$m<<$n>>».[0]
Use an unspace. (can never be inside of an operator so will split them up)
$m<<$n>>\.[0]
$m<<$n>>\ .[0]
I think this is a bug, as it doesn't make much sense to be matching a hyper postfix inside of a quotewords statement.
(It doesn't affect $m<<1>>.elems)
I am creating a tokeniser in ML-Lex a part of the definition of which is
datatype lexresult = STRING
| STRINGOP
| EOF
val error = fn x => TextIO.output(TextIO.stdOut,x ^ "\n")
val eof = fn () => EOF
%%
%structure myLang
digit=[0-9];
ws=[\ \t\n];
str=\"[.*]+\";
strop=\[[0-9...?\^]\];
%s alpha;
alpha=[a-zA-Z];
%%
<alpha> {alphanum}+ => (ID);
. => (error ("myLang: ignoring bad character " ^ yytext); lex());
I want that the type ID should be detected only when it starts with or is found after "alpha". I know that writing it as
{alpha}+ {alphanum}* => (ID);
is an option but I need to learn to use the use of start states as well for some other purposes. Can someone please help me on this?
The information you need is in the documentation which comes with SML available in various places. Many university courses have online notes which contain working examples.
The first thing to note from your example code is that you have overloaded the name alpha and used it to name a state and a pattern. This is probably not a good idea. The pattern alphanum is not not defined, and the result ID is not declared. Some basic errors which you should probably fix before thinking about using states - or posting a question here on SO. Asking for help for code with such obvious faults in it is not encouraging help from the experts. :-)
Having fixed up those errors, we can start using states. Here is my version of your code:
datatype lexresult = ID
| EOF
val error = fn x => TextIO.output(TextIO.stdOut,x ^ "\n")
val eof = fn () => EOF
%%
%structure myLang
digit=[0-9];
ws=[\ \t\n];
str=\"[.*]+\";
strop=\[[0-9...?\^]\];
%s ALPHA_STATE;
alpha=[a-zA-Z];
alphanum=[a-zA-Z0-9];
%%
<INITIAL>{alpha} => (YYBEGIN ALPHA_STATE; continue());
<ALPHA_STATE>{alphanum}+ => (YYBEGIN INITIAL; TextIO.output(TextIO.stdOut,"ID\n"); ID);
. => (error ("myLang: ignoring bad character " ^ yytext); lex());
You can see I've added ID to the lexresult, named the state ALPHA_STATE and added the alphanum pattern. Now lets look at how the state code works:
There are two states in this program, they are called INITIAL and ALPHA_STATE (all lex programs have an INITIAL default state). It always begins recognising in the INITIAL state. Having a rule <INITIAL>{alpha} => indicates that if you encounter a letter when in the initial state (i.e. NOT in the ALPHA_STATE) then it is a match and the action should be invoked. The action for this rule works as follows:
YYBEGIN ALPHA_STATE; (* Switch from INITIAL state to ALPHA_STATE *)
continue() (* and keep going *)
Now we are in ALPHA_STATE it enables those rules defined for this state, which enable the rule <ALPHA_STATE>{alphanum} =>. The action on this rule switch back to the INITIAL state and record the match.
For a longer example of using states (lex rather than ML-lex) you can see my answer here: Error while parsing comments in lex.
To test this ML-LEX program I referenced this helpful question: building a lexical analyser using ml-lex, and generated the following SML program:
use "states.lex.sml";
open myLang
val lexer =
let
fun input f =
case TextIO.inputLine f of
SOME s => s
| NONE => raise Fail "Implement proper error handling."
in
myLang.makeLexer (fn (n:int) => input TextIO.stdIn)
end
val nextToken = lexer();
and just for completeness, it generated the following output demonstrating the match:
c:\Users\Brian>"%SMLNJ_HOME%\bin\sml" main.sml
Standard ML of New Jersey v110.78 [built: Sun Dec 21 15:52:08 2014]
[opening main.sml]
[opening states.lex.sml]
[autoloading]
[library $SMLNJ-BASIS/basis.cm is stable]
[autoloading done]
structure myLang :
sig
structure UserDeclarations : <sig>
exception LexError
structure Internal : <sig>
val makeLexer : (int -> string) -> unit -> Internal.result
end
val it = () : unit
hello
ID
I attempted to write a C-style for-loop in REBOL:
for [i: 0] [i < 10] [i: i + 1] [
print i
]
This syntax doesn't appear to be correct, though:
*** ERROR
** Script error: for does not allow block! for its 'word argument
** Where: try do either either either -apply-
** Near: try load/all join %/users/try-REBOL/data/ system/script/args...
Does REBOL have any built-in function that is similar to a C-style for loop, or will I need to implement this function myself?
The equivalent construct in a C-like language would look like this, but I'm not sure if it's possible to implement the same pattern in REBOL:
for(i = 0; i < 10; i++){
print(i);
}
Because of the rebol3 tag, I'll assume this question pertains to Rebol 3.
Proposed "CFOR" for Rebol 3
For Rebol 3, there is a proposal (which got quite a bit of support) for a "general loop" very much along the lines of a C-style for and therefore currently going under the name of cfor as well: see CureCode issue #884 for all the gory details.
This includes a much refined version of Ladislav's original implementation, the current (as of 2014-05-17) version I'll reproduce here (without the extensive inline comments discussing implementation aspects) for the sake of easy reference:
cfor: func [ ; Not this name
"General loop based on an initial state, test, and per-loop change."
init [block! object!] "Words & initial values as object spec (local)"
test [block!] "Continue if condition is true"
bump [block!] "Move to the next step in the loop"
body [block!] "Block to evaluate each time"
/local ret
] [
if block? init [init: make object! init]
test: bind/copy test init
body: bind/copy body init
bump: bind/copy bump init
while test [set/any 'ret do body do bump get/any 'ret]
]
General problems with user-level control structure implementations in Rebol 3
One important general remark for all user-level implementation of control constructs in Rebol 3: there is no analogue to Rebol 2's [throw] attribute in R3 yet (see CureCode issue #539), so such user-written ("mezzanine", in Rebol lingo) control or loop functions have problems, in general.
In particular, this CFOR would incorrectly capture return and exit. To illustrate, consider the following function:
foo: function [] [
print "before"
cfor [i: 1] [i < 10] [++ i] [
print i
if i > 2 [return true]
]
print "after"
return false
]
You'd (rightly) expect the return to actually return from foo. However, if you try the above, you'll find this expectation disappointed:
>> foo
before
1
2
3
after
== false
This remark of course applies to all the user-level implementation given as answers in this thread, until bug #539 is fixed.
There is an optimized Cfor by Ladislav Mecir
cfor: func [
{General loop}
[throw]
init [block!]
test [block!]
inc [block!]
body [block!]
] [
use set-words init reduce [
:do init
:while test head insert tail copy body inc
]
]
The other control structure that most people would use in this particular case is repeat
repeat i 10 [print i]
which results in:
>> repeat i 10 [print i]
1
2
3
4
5
6
7
8
9
10
I generally do no use loop very often, but it can be used to a similar extent:
>> i: 1
>> loop 10 [print ++ i]
1
2
3
4
5
6
7
8
9
10
Those are some useful control structures. Not sure if you were looking for cfor but you got that answer from others.
I have implemented a function that works in the same way as a C for loop.
cfor: func [init condition update action] [
do init
while condition [
do action
do update
]
]
Here's an example usage of this function:
cfor [i: 0] [i < 10] [i: i + 1] [
print i
]
For simple initial value, upper limit and step, following works:
for i 0 10 2
[print i]
This is very close to C for loop.