FS0010: Unexpected keyword in binding - f#

I am trying to follow the docs to create an f# program in Visual studio Code
When I highlight my code and press Alt Enter to run in the interactive window I get an error
Script.fsx(8,5):error FS0010: Unexpected keyword in binding. Expected incomplete structured construct at or before this point or other token.
[Update]
I tried several times to get this to work, highlighting the code as the image shows.
Strangely after leaving the computer an hour, I now can no longer repeat the problem.

The output visible in the interactive window suggests that your selection when you pressed Alt+Enter was different from the selection you're showing in the screenshot. More specifically, the selection you executed started with let isVowel (without leading spaces) and ended with word.[0] then.
Even more specifically, the code you tried to execute was this:
let isVowel (c: char) =
match c with
| 'a' | 'e' | 'i' |'o' |'u'
| 'A' | 'E' | 'I' | 'O' | 'U' -> true
|_ -> false
if isVowel word.[0] then
This code does not compile for several reasons. First, there is nothing after then. Second, the if is indented incorrectly: it needs to be indented either to the same position as match (in which case it will be considered part of isVowel definition) or to the same position as let isVowel (in which case it will be considered part of the same block as isVowel), but here it is neither - to the right of let isVowel, but to the left of match.
If you wanted to execute just the definition of isVowel, then you shouldn't have included the if in the selection.
If you wanted to execute the whole definition of toPigLatin, then you should have included the let toPigLatin line and the whole if/else expression.

Related

How to write nearley grammar without loop?

I'm trying to use nearley.js to write a parse for ini-like files, with difference that string value may contain special control symbols. For example ^y mean the text after this symbol must be yellow, ^b - blue, &i - italic.
I use nearley playground (http://omrelli.ug/nearley-playground/) and started with very basic grammar for value:
VALUE -> FONT_MODIFIER | COLOR_MODIFIER | TEXT
TEXT -> [^\n\^\&]:+
FONT_MODIFIER -> "&" [iIbBsS]
COLOR_MODIFIER -> "^" [aAbBcCdDfFgGiIkKmMoOpPrRsSwWyYnN]
But after I add test with random text (just letters, like "asdassad") after few seconds it gives me error Possible infinite loop detected! Check your grammar for infinite recursion.
What am I doing wrong? I just can't see where the loop comes from.

how to make terminal rule case insensitive?

I have a scenario where a statement/rule can appear anywhere in the whole code. This statement starts with a keyword and if this keyword appears, i need to skip the whole content till i reach ';'.
I tried addressing this by defining a terminal rule as below:
terminal stmt: 'TEMP' -> ';';
However my whole code is case insensitive and terminal rules are not. How do i make terminal rule case insensitive? Or is there a alternative way in which all my conditions for this statement are satisfied?
you can do the following
terminal THINGY:
('T' | 't') ('E' | 'e')
('M' | 'm') ('P' | 'p')->";";

FsLex aborts with parse error on '{'

My Lexer is supposed to distinguish brackets and maintain a stack of opened brackets during lexing. For this I specified a helper function in my fsl file like this:
let updateBracketStack sign = // whenever a bracket is parsed, update the stack accordingly
match sign with
| '[' -> push sign
| '{' -> push sign
| ']' -> if top() = '[' then pop() else ()
| '}' -> if top() = '{' then pop() else ()
| _ -> ()
The stack of course is a ref of char list. And push, top, pop are implemented accordingly.
The problem is that everything worked up until I added the { character. Now FsLex simply dies with error: parse error
If I change the characters to strings, i.e. write "{" FsLex is fine again, so a workaround would be to change the implementation to a stack of strings instead of characters.
My question is however, where does this behaviour come from? Is this a bug if FsLex?
FsLex's parser is generated using FsLexYacc. The message "parse error" means the lexing (of your .fsl file) until error position is succeeded but parsing is failed at that position. To find the root cause you will need to post full input text to FsLex.
This is only guess. FsLex could be confused by '{' character since it is also open token for embedded code block? Or your input text contains some special unicode characters but it looks like whitespace on editor?
One possible workaround is, to create another module and .fs file, LexHelper module in LexHelper.fs, and place your helper functions in it, and open it from .fsl file.
EDIT
Looking at the source code of FsLexYacc, it doesn't handle } character enclosed by single-quotes in embedded F# code, but does when enclosed by double-quotes.
https://github.com/fsprojects/FsLexYacc/blob/master/src/FsLex/fslexlex.fsl

F# error FS0597 possibly caused by incorrect indentation

I have the following piece of code:
if File.Exists(settingsFilePath) = false then
System.Console.WriteLine("Are you running BlogDotNet for the first time? (yes/no):");
match System.Console.ReadLine() with
| "yes" ->
try
()
with
| :? System.UnauthorizedAccessException -> System.Console.WriteLine("You don't have write permissions on the current directory, please move to another one!")
| :? System.IOException -> System.Console.WriteLine("Couldn't one or more of the create the necessary directories and files, an unknown IO related exception occured")
| "no" -> System.Console.WriteLine("Then you must be running blogctl while in a wrong directory,")
System.Console.WriteLine("please move to the correct directory first before attempting to issue any further blogctl commands")
| _ -> System.Console.WriteLine("Invalid answer, please answer with either 'yes' or 'no'")
else
match List.ofArray (System.Environment.GetCommandLineArgs().[1..]) with
| [""] | ["help"] | ["--help"] | ["-h"] -> ()
| _ -> System.Console.WriteLine("Invalid command or command with invalid arguments, run 'blogctl help' to get a list of the available commands")
System.Console.WriteLine("and information about their usage")
The compiler keeps complaining with "error FS0597: Successive arguments should be separated by spaces or tupled, and arguments involving function or method applications should be parenthesized" at the last line and at line 12. Now as you can see at the code listing above those lines are indeed incorrectly indented, but when I copied them from my editor (Visual Studio Code) they were correctly indented. I have tried multiple times to remove the indentation and indent them again, to no avail, the compiler just keeps complaining. When I put the 2 Console.WriteLine() expressions on one line after the arrow and separate them by a semicolon the compiler stops complaining.

What's with "Uppercase variable identifiers should not generally be used in patterns..."?

This compiler like:
let test Xf Yf = Xf + Yf
This compiler no like:
let test Xfd Yfd = Xfd + Yfd
Warning:
Uppercase variable identifiers should not generally be used in patterns, and may indicate a misspelt pattern name.
Maybe I'm not googling properly, but I haven't managed to track down anything which explains why this is the case for function parameters...
I agree that this error message looks a bit mysterious, but there is a good motivation for it. According to the F# naming guidelines, cases of discriminated unions should be named using PascalCase and the compiler is trying to make sure that you don't accidentally misspell name of a case in pattern matching.
For example, if you have the following union:
type Side =
| Left
| Right
You could write the following function that prints "ok" when the argument is Left and "wrong!" otherwise:
let foo a =
match a with
| Lef -> printfn "ok"
| _ -> printfn "wrong!"
There is a typo in the code - I wrote just Lef - but the code is still valid, because Lef can be interpreted as a new variable and so the matching assigns whatever side to Lef and always runs the first case. The warning about uppercase identifiers helps to avoid this.
F# tries to enforce case rules for active patterns - consider what does this code do
let f X =
match X with
|X -> 1
|_ -> 2
This is quite confusing. Also, function parameters are similar to patterns, you can do
let f (a,b,_) = a,b
for example. Not quite sure why the third letter triggers the warning though

Resources