EBNF Colon and Semicolon usage? - bnf

I have no idea what a colon means in BNF or EBNF. It's not listed anywhere on the internet. Anyway, my professor decided to assign it in the homework. I think he is confusing it with a semicolon or something. I'm still not even sure what the semicolon means. Here is some context:
Given the following CFG (context free grammar) for declarations:
D -> D ; D
D -> id : T
T -> char
T -> integer
Give an attribute grammar that defines type of an identifier (id stands for identifier).
Anyone think they can help?

; and : are simply terminals, just like id, char and integer. So your code could be something like this:
x : char ; y : integer ; z : char

Related

Standard ML: Truncating String

I know ML has a bunch of string methods (substring, etc) that would make this easier but I want to get more comfortable with the language, so I'm implementing some myself.
I'm trying to truncate a string, i.e. cut off the string after a certain number of characters. I think I'm very close but am getting a syntax error when I do
val x::xs = explode(myString);
Here's the full code:
fun getAllButLast([x]) = nil
| getAllButLast(x::xs) = x::getAllButLast(xs);
fun truncate(myString, 0) = ""
| truncate(myString, limit:int) =
let
val x::xs = explode(myString);
in
x::truncate(implode(getAllButLast(xs)), limit - 1)
end;
Thoughts on why the compiler doesn't like this?
val x::xs = explode(myString);
Thanks for the help,
bclayman
Edit to include error:
Ullman.sml:82.5-82.55 Error: operator and operand don't agree [tycon mismatch]
operator domain: char * char list
operand: char * string
in expression:
x :: truncate (implode (getAllButLast <exp>),limit - 1)
uncaught exception Error
raised at: ../compiler/TopLevel/interact/evalloop.sml:66.19-66.27
../compiler/TopLevel/interact/evalloop.sml:44.55
../compiler/TopLevel/interact/evalloop.sml:292.17-292.20
As the error message shows, it is complaining about a different line. And it is complaining because the right operand of the :: operator in that line (the result of the recursive call to truncate) is a string, not a list. You probably want to use ^ instead, which denotes string concatenation.
Hint: There are other issues with your code. At least it is extremely inefficient. You should generally avoid implode/explode, but if you must use them, you should at least only call each of them once for the whole string, and not once for every character in the recursion.

UnsafeMutablePointer<Int8> from String in Swift

I'm using the dgeev algorithm from the LAPACK implementation in the Accelerate framework to calculate eigenvectors and eigenvalues of a matrix. Sadly the LAPACK functions are not described in the Apple Documentation with a mere link to http://netlib.org/lapack/faq.html included.
If you look it up, you will find that the first two arguments in dgeev are characters signifying whether to calculate eigenvectors or not. In Swift, it is asking for UnsafeMutablePointer<Int8>. When I simply use "N", I get an error. The dgeev function and the error are described in the following screenshot
What should I do to solve this?
The "problem" is that the first two parameters are declared as char *
and not as const char *, even if the strings are not modified by the function:
int dgeev_(char *__jobvl, char *__jobvr, ...);
is mapped to Swift as
func dgeev_(__jobvl: UnsafeMutablePointer<Int8>, __jobvr: UnsafeMutablePointer<Int8>, ...) -> Int32;
A possible workaround is
let result = "N".withCString {
dgeev_(UnsafeMutablePointer($0), UnsafeMutablePointer($0), &N, ...)
}
Inside the block, $0 is a pointer to a NUL-terminated array of char with the
UTF-8 representation of the string.
Remark: dgeev_() does not modify the strings pointed to by the first two arguments,
so it "should be" declared as
int dgeev_(const char *__jobvl, const char *__jobvr, ...);
which would be mapped to Swift as
func dgeev_(__jobvl: UnsafePointer<Int8>, __jobvr: UnsafePointer<Int8>, ...) -> Int32;
and in that case you could simply call it as
let result = dgeev_("N", "N", &N, ...)
because Swift strings are converted to UnsafePointer<Int8>) automatically,
as explained in String value to UnsafePointer<UInt8> function parameter behavior.
It is ugly, but you can use:
let unsafePointerOfN = ("N" as NSString).UTF8String
var unsafeMutablePointerOfN: UnsafeMutablePointer<Int8> = UnsafeMutablePointer(unsafePointerOfN)
and use unsafeMutablePointerOfN as a parameter instead of "N".
With Swift 4.2 and 5 you can use this similar approach
let str = "string"
let unsafePointer = UnsafeMutablePointer<Int8>(mutating: (str as NSString).utf8String)
You can get the result from unsafePointer.

Pass a string value in a recursive bison rule

i'm having some issues on bison (again).
I'm trying to pass a string value between a "recursive rule" in my grammar file using the $$,
but when I print the value I have passed, the output looks like a wrong reference ( AU�� ) instead the value I wrote in my input file.
line: tok1 tok2
| tok1 tok2 tok3
{
int len=0;
len = strlen($1) + strlen($3) + 3;
char out[len];
strcpy(out,$1);
strcat(out," = ");
strcat(out,$3);
printf("out -> %s;\n",out);
$$ = out;
}
| line tok4
{
printf("line -> %s\n",$1);
}
Here I've reported a simplified part of the code.
Giving in input the token tok1 tok2 tok3 it should assign to $$ the out variable (with the printf I can see that in the first part of the rule the out variable has the correct value).
Matching the tok4 sequentially I'm in the recursive part of the rule. But when I print the $1 value (who should be equal to out since I have passed it trough $$), I don't have the right output.
You cannot set:
$$ = out;
because the string that out refers to is just about to vanish into thin air, as soon as the block in which it was declared ends.
In order to get away with this, you need to malloc the storage for the new string.
Also, you need strlen($1) + strlen($3) + 4; because you need to leave room for the NUL terminator.
It's important to understand that C does not really have strings. It has pointers to char (char*), but those are really pointers. It has arrays (char []), but you cannot use an array as an aggregate. For example, in your code, out = $1 would be illegal, because you cannot assign to an array. (Also because $1 is a pointer, not an array, but that doesn't matter because any reference to an array, except in sizeof, is effectively reduced to a pointer.)
So when you say $$ = out, you are making $$ point to the storage represented by out, and that storage is just about to vanish. So that doesn't work. You can say $$ = $1, because $1 is also a pointer to char; that makes $$ and $1 point to the same character. (That's legal but it makes memory management more complicated. Also, you need to be careful with modifications.) Finally, you can say strcpy($$, out), but that relies on $$ already pointing to a string which is long enough to hold out, something which is highly unlikely, because what it means is to copy the storage pointed to by out into the location pointed to by $$.
Also, as I noted above, when you are using "string" functions in C, they all insist that the sequence of characters pointed to by their "string" arguments (i.e. the pointer-to-character arguments) must be terminated with a 0 character (that is, the character whose code is 0, not the character 0).
If you're used to programming in languages which actually have a string datatype, all this might seem a bit weird. Practice makes perfect.
The bottom line is that what you need to do is to create a new region of storage large enough to contain your string, like this (I removed out because it's not necessary):
$$ = malloc(len + 1); // room for NUL
strcpy($$, $1);
strcat($$, " = ");
strcat($$, $3);
// You could replace the strcpy/strcat/strcat with:
// sprintf($$, "%s = %s", $1, $3)
Note that storing mallocd data (including the result of strdup and asprintf) on the parser stack (that is, as $$) also implies the necessity to free it when you're done with it; otherwise, you have a memory leak.
I've solved it changin the $$ = out; line into strcpy($$,out); and now it works properly.

Recursive List Creation Function. Errors in type

I have an Ocaml function that is giving me errors.
What I am trying to do:
Recursively create a List of random numbers (0-2) of size "limit".
Here's what I have:
let rec carDoorNumbers = fun limit ->
match limit with
| [1] -> Random.int 3
| [] -> Random.int 3 :: carDoorNumbers (limit-1);;
I am getting this error:
Error: This expression has type 'a list
but an expression was expected of type int
Think about what your function has to do: given a limit, you have to create a list of numbers. So your type is something like carDoorNumbers : int -> int list.
Looking at that, it seems you have two errors. First, you're matching limit (which should be an int) against a list pattern. [1] -> ... matches a list containing only the element 1 and [] matches the empty list; you really want to match against the number 1 and any other number n.
The second error is that you return two different types in your match statement. Remember that you are supposed to be returning a list. In the first case, you are returning Random.int 3, which is an int rather than an int list. What you really want to return here is something like [Random.int 3].
The error you got is a little confusing. Since the first thing you returned was an int, it expects your second thing to also be an int. However, your second case was actually correct: you do return an int list! However, the compiler does not know what you meant, so its error is backwards; rather than changing the int list to an int, you need to change the int to an int list.
Your match expression treats limit like a list. Both [1] and [] are lists. That's what the compiler is telling you. But it seems limit should be an integer.
To match an integer, just use an integer constant. No square brackets.
(As a side comment, you might want to be sure the function works well when you pass it 0.)

What's wrong with groovy math?

This seems quite bizarre to me and totally putting me on the side of people willing to use plain java. While writing a groovy based app I encountered such thing:
int filesDaily1 = (item.filesDaily ==~ /^[0-9]+$/) ?
Integer.parseInt(item.filesDaily) : item.filesDaily.substring(0, item.filesDaily.indexOf('.'))
def filesDaily = (item.filesDaily ==~ /^[0-9]+$/) ?
Integer.parseInt(item.filesDaily) : item.filesDaily.substring(0, item.filesDaily.indexOf('.'))
So, knowing that item.filesDaily is a String with value '1..*' how can it possibly be, that filesDaily1 is equal to 49 and filesDaily is equal to 1?
What's more is that when trying to do something like
int numOfExpectedEntries = filesDaily * item.daysToCheck
an exception is thrown saying that
Cannot cast object '111' with class 'java.lang.String' to class 'int'
pointing to that exact line of code with multiplication. How can that happen?
You're assigning this value to an int:
item.filesDaily.substring(0, item.filesDaily.indexOf('.'))
I'm guessing that Groovy is converting the single-character string "1" into the char '1' and then taking the Unicode value in the normal char-to-int conversion... so you end up with the value 49.
If you want to parse a string as a decimal number, use Integer.parseInt instead of a built-in conversion.
The difference between filesDaily1 and filesDaily here is that you've told Groovy that filesDaily1 is meant to be an int, so it's applying a conversion to int. I suspect that filesDaily is actually the string "1" in your test case.
I suspect you really just want to change the code to something like:
String text = (item.filesDaily ==~ /^[0-9]+$/) ? items.filesDaily :
item.filesDaily.substring(0, item.filesDaily.indexOf('.'))
Integer filesDaily = text.toInteger()
This is a bug in the groovy type conversion code.
int a = '1'
int b = '11'
return different results because different converters are used. In the example a will be 49 while b will be 11. Why?
The single-character-to-int conversion (using String.charAt(0)) has a higher precedence than the integer parser.
The bad news is that this happens for all single character strings. You can even do int a = 'A' which gives you 65.
As long as you have no way of knowing how long the string is, you must use Integer.parseInt() instead of relying on the automatic type conversion.

Resources