I want to be able to parse between 2 marks in parse rule. For a contrieved example:
src: {a b c d e f}
rule: [
to "b" mark1: thru "e" mark2:
to mark1 copy text to mark2
]
This doesn't work, text contains "[" instead of what I'd like to get:
b c d e
You're trying to implement a "DO desire" of copying using PARSE. PARSE's COPY is looking for patterns, not treating the series as positions.
You can escape into DO in mid-parse via a PAREN!, it will run if the parse rule reaches that point.
src: {a b c d e f}
rule: [
to "b" mark1: thru "e" mark2:
(text: copy/part mark1 mark2)
to end ;-- not strictly necessary, but makes PARSE return true
]
parse src rule
That will give you text as b c d e
Note that you can't have it both ways, either with COPY or with TO. TO <series!> meant "look for b", not "jump to the position of b". So when you say to mark1 you're invoking another match. If you want to set the parse position to the specific position recorded in mark1, use :mark1 in the parse rule.
two alternative solutions/rules working in Red
rule: [
to "b" copy text thru "e" to end
]
and
rule: [ to "b" collect [keep thru "e"] to end]
text: first parse src rule
Related
In C, local variables exist inside of a function and contain the values like this:
void main(){
int a = 5;
int b = 9;
}
In the Gforth manual, they describe the local variables like this:
: swap { a b -- b a }
b a ;
1 2 swap .s 2drop
but it seems like a function which is taking two arguments, a and b.
Another tutorial on the Forth language shows a variable like this:
variable a
3 a ! ( ! to store the value )
So, which one is correct?
In Forth, local variables are described by the following syntax (see also 13.6.2.2550 {:):
{: args [ | vals ] [ –– outs ] :}
where each of args, vals and outs represents space-delimited names (the parts in square brackets are optional). These names are interpreted as follows:
args names are for locals that are initialized from the data stack, with the top of the stack being assigned to the rightmost name in args;
vals names are for locals that are uninitialized;
outs names are ignored (they are for documentation purposes only, if any).
Gforth uses { ... } notation for locals as an alternative to the standard one.
So, swap can be defined as:
: swap {: a b :} b a ;
It takes two values from the stack into a and b local variables, and then puts them back on the stack in the reversed order.
An example of use an uninitialized local variable:
: exch ( x2 addr -- x1 ) {: a | x1 :}
a # to x1 a ! x1
;
The optional -- ... part is allowed to mimic a stack diagram, i.e., to unite the declaration of locals and the stack diagram for a word. For example:
: umin {: u2 u1 -- u2|u1 :} u2 u1 u< if u2 else u1 then ;
Without special optimizations, performance of local variables is slightly worse than of a little stack juggling.
I'm beginner in F#, What does %-5s and %5s do in the following code? I thought it gives space paddings but I'm not sure how it pads?
printfn "%-5s %5s" "a" "b"
When I tried printf "%-5s %5s" "a" "b" "v"
or printf "%-5s %-5s" "a" "b" "c"
That gives me an type match error, I don't understand the syntax, It dosen't seem that it is printing the concatenation of the three strings "%-5s %5s", "a" and "b". It seems to put "a" and "b" between the %5s. so why can't I add "c" after? Also, I'm following tutorial on Youtube: https://www.youtube.com/watch?v=c7eNDJN758U
If There is any other good source of learning the essence of functional language by F#, please give some suggesting!
The %5s and %-5s are formatting codes along with width and alignments specified.
The hyphen in your first code aligns the value to the left.
As an example, I have the following 2 lines:
printfn "%-5s %5s" "a" "b"
printfn "%-5s %5s" "yo" "hey!"
What gets printed is the following:
a b
yo hey!
Here is a page that explains more about the printfn function. The entire site is an excellent resource for learning to use F#.
Good luck!
PS - as for your question about the error when adding the 3rd parameter, the printfn function will check for both the types and number of parameters you supply based on the format codes in the string. This is explained in the linked page I included earlier.
I'm working on implementation of the Google Protobuf compiler for proto files in Prolog for generating Prolog programs. Prolog is SWI-Prolog.
I'm translating EBNF definitions into DCG and ran across a few problems:
I have to deal with [ ... ] and { ... } EBNF construct - meaning optional ( executable zero or one times ) and repeatative( executable any number of times );
I have to insert the callbacks into DCG code to implement the part of compiler functionality (syntax switching/importing/ etc.) using DCG's construct { ... }, which allows goals in Prolog syntax inside DCG rules.
I'm applying for optional and repeatative the meta-predicates: $$rep/1, $$opt/1:
EBNF
decimals = decimalDigit { decimalDigit }
exponent = ( "e" | "E" ) [ "+" | "-" ] decimals
DCG
decimals --> decimalDigit, '$$rep'( decimalDigit ).
exponent --> ( "e"; "E" ), '$$opt'( "+"; "-" ), decimals.
'$$rep'( Goal ) :- repeat, call(Goal); !, fail.
'$$opt'( Goal ) :- once(Goal) ; \+ Goal.
"Callback:"
import --> "import", opt(( "weak" ; "public", { record(public)} )), strLit,
{
import(public, strlit )
}, ";".
Looking awkward (if not to say ugly) for me...
Questions:
What's wrong with my solutions?
Should I manually translate EBNG into DCG without using meta-predicates?
What is the alternative for the awkward penetration into a DCG rule?
From a quick first glance, the main issue is that you are uncleanly intermingling DCGs with regular Prolog predicates.
Stay within DCGs to define all nonterminals. For example:
optional(NT) --> [] | NT.
once_or_more(NT) --> NT, or_more(NT).
or_more(NT) --> [] | NT, or_more(NT).
With the following example definition:
a --> [a].
We can post:
?- phrase(optional(a), Ls).
Ls = [] ;
Ls = [a].
?- phrase(once_or_more(a), Ls).
Ls = [a] ;
Ls = [a, a] ;
Ls = [a, a, a] ;
Ls = [a, a, a, a] ;
Ls = [a, a, a, a, a] .
This seems to work as you need it.
For the callback, you can simply pass around the predicate that you need to call, with the general outline:
parse_with_callback(Goal) -->
...,
{ Goal },
...
This seems quite OK.
If such patterns arise frequently, you can always consider generating such DCGs from a different representation that lets you represent the task more cleanly.
I am working on a toy parser in golang just to learn the language. I added a test case with grammar covering the following cases:
Valid:
a, ab, aba, ababababababa, ababababab
b, ba, bab, babababababab, bababababa
Invalid:
abb, baa
a is always followed by b and vice versa.
Now the grammar in my parser looks like that (I omit the surrounding code for sake of brevity):
"expr": Or(Ref("A"), Ref("B")),
"A": And(
a,
Optional(
And(
b,
Optional(Ref("A"))))),
"B": And(
b,
Optional(Ref("A")))
Where
a - exact match for "a" character
b - exact match for "b" character
"A", "B", "expr" - names of the parts of the grammar that can be referred
later with Ref("A")
And - consume sequence of expressions
Or - consume any of the expressions
Ref - refer to other expression (allows recursion)
Optional - make the expression non-obligatory
I guess it is not the most succinct way to describe this grammar. How to make it more compact?
Related:
Why can't a recursive-descent parser handle left recursion
EDIT:
The BNF answer from Filip can be written in my syntax as:
"expr": Or(Ref("A"), Ref("B")),
"A": Or(And(a, Ref("B")), a),
"B": Or(And(b, Ref("A")), b)
The BNF grammar you have is this:
expr ::= A | B
A ::= "a" B | "a"
B ::= "b" A | "b"
which I think translates to this using your syntax:
"expr": Or(Ref("A"), Ref("B")),
"A": And(
a,
Optional(Ref("B"))),
"B": And(
b,
Optional(Ref("A")))
Note that it is important to check terminals ("a", "b") before non-terminals (Ref(x)), or you'll get an infinite loop. It would always try to see if it could match another A or B to the end of the string, and then another, and another, causing a never ending recursion.
I would like to be able to input a sequence of integers on one line, such as:
97, 128, 125, 17, 2
and have the Haskell program convert the input into a list of integers, such as:
[97, 128, 135, 17, 2]
so that I can do some math operations like zipWith(ing) the list with another list of integers. Having trouble with this. I tried using the read and words functions but I wasn't able to achieve the expected result. Any ideas?
One possible (again, quick'n'dirty) solution is to use read with the instance defined for lists, which expects strings in the format [item1, item2, item3...]:
convert :: String -> [Int]
convert s = read $ "[" ++ s ++ "]"
A more robust solution would be parsing with filter or similar (as shown in the other answer) or using a parsing library to do the job properly.
The problem with only using words is that the comma (,) will still be included.
A quick-and-dirty hack is probably to first map all characters instead of digits to a space:
import Data.Char(isDigit)
cnv x | isDigit x = x
| otherwise = ' '
and then use:
map read . words . map cnv :: Read b => [Char] -> [b]
demo
*Main> ((map read . words . map cnv) "97, 128, 125, 17, 2" :: [Int]
[97,128,125,17,2]
A potential problem is of course that you omit [A-z] characters, etc. Furthermore this approach is not the most efficient.
An advantage is that by using read all items that can be read are still candidates to process the stream of "words".
Why not filtering?
One can also use a filter evidently to obtain for instance only spaces and digits. For instance
map read . words . filter (\x -> isDigit x || isSpace x)
A potential problem is that it is possible that the numbers are not separated by spaces ( ), but only by commas (,), semi-colons (;), etc. Working with the above expression generates the correct result:
(map read . words . filter (\x -> isDigit x || isSpace x)) "97, 128, 125, 17, 2" :: [Int]
[97,128,125,17,2]
but
(map read . words . filter (\x -> isDigit x || isSpace x)) "97,128,125,17,2" :: [Int]
[97128125172]
doesn't.
The task you're specifying falls under the category of textual parsing. When facing such a problem the safe bet is to approach it with either the "parsec" or the "attoparsec" library. Those libraries provide APIs which abstract over parsing in a safe and composable (hence scalable) way.
Here's how you'd write the "attoparsec" parser for your task:
listOfInts :: Parser [Int]
listOfInts =
sepBy decimal separator
where
separator =
skipSpace *> char ',' *> skipSpace
Note that the provided implementation already allows you to parse a not well formed input, where the separator might have multiple or no spaces before and after the comma. Also note how simple it is to express this already complicated condition using such a parser.
Thank you all for your help. For my application, this seems to work well:
myInput <- getLine
123 23 345 23
(map read . words) myInput::[Int]
I was having a little trouble understanding why the parenthesis go where they do, but this seems to work also:
myInput <- getLine
234 34 235 465 34
map read $ words myInput::[Int]
Since I'm just using spaces to separate the numbers, I don't have to use the filter, but thanks for posting it because now I understand the syntax better.
Don