I'm getting this error when trying to run a parser written in JavaCC on a sample (syntactically valid) file:
Exception in thread "main" ParseException: Encountered "8;" at line 13, column 17.
Was expecting one of:
<INT_CONST> ...
"<" ...at jimpleParser.generateParseException(jimpleParser.java:2421)
at jimpleParser.jj_consume_token(jimpleParser.java:2292)
at jimpleParser.expr(jimpleParser.java:1038)
(shortened for conciseness)
I cannot work out why it is throwing an error. "8" should be a valid token. Here is the function in question:
String expr():
{
Token t1 = null, t2 = null;
String f1 = null, f2 = null, f3 = null;
}
{
(LOOKAHEAD(3)
f1 = imm() {System.out.println(f1);}
| f1 = new_expr()
| t1 = <LBR> f2 = nonvoid_type() t2 = <RBR> f3 = imm()
{f1 = t1.image.concat(f2.concat(t2.image.concat(f3)));}
| LOOKAHEAD(2)
f2 = imm() t1 = <INSTANCEOF> f3 = nonvoid_type()
{f1 = f2.concat(t1.image.concat(f3));}
| f1 = invoke_expr()
| LOOKAHEAD(2)
f1 = reference()
| LOOKAHEAD(2)
f1 = binop_expr()
| f1 = unop_expr())
{return f1;}
}
which should in turn call imm shown here:
String imm():
{
String f1 = null;
}
{
(f1 = constant()
| f1 = local_name())
{return f1;}
}
which should in turn call constant shown here:
String constant():
{
Token t1 = null, t2 = null;
String f1 = null;
}
{
(t1 = <INT_CONST> {f1 = t1.image; System.out.println(f1);}
| t1 = <FLOAT_CONST> {f1 = t1.image;}
| t1 = <MIN_INT_CONST> {f1 = t1.image;}
| t1 = <MIN_FLOAT_CONST> {f1 = t1.image;}
| t1 = <STRING_CONST> {f1 = t1.image;}
| t1 = <CLASS> t2 = <STRING_CONST> {f1 = t1.image.concat(t2.image);}
| t1 = <NULL> {f1 = t1.image;})
{return f1;}
}
8 should be an INT_CONST. Relevant token specifications are shown here:
<INT_CONST: ((<OCT_CONST> | <DEC_CONST> | <HEX_CONST>) ("L")?)>
<DEC_CONST: (<DEC_DIGIT>)+>
<DEC_DIGIT: ["0"-"9"]>
Any help would be much appreciated. Thanks
Note that it is not "8" that is causing the problem, but "8;". Although "8" is an INT_CONST, "8;" is not. So the longest match rule is kicking in and some other token production that does match "8;" is winning. See the FAQ http://www.engr.mun.ca/~theo/JavaCC-FAQ/ question 3.3. Without seeing all of your .jj file, I can't tell you which token it is, but if you put a break point on the code that constructs the error message you can easily see what the .kind field of the unexpected token holds.
Try this in your token section, it would definitely solve your problem:
TOKEN:
{
<DEC_DIGIT: (["0"-"9"])>
|
<INT_CONST: ((<OCT_CONST> | <DEC_CONST> | <HEX_CONST>) ("L")?)>
|
<DEC_CONST: (<DEC_DIGIT>)+>
// The rest of your tokens....
}
Related
string and string | number are compatible, but { [string]: string } and { [string]: (string | number} } are incompatible.
Am i doing something wrong?
https://flow.org/try/#0PQKgBAAgZgNg9gdzCYAoVAXAngBwKZgAqAjGALxgDOGATgJYB2A5gNya4GEBM5VtjTMAB8wDAK4BbAEZ4abbPiIBmXgG8wAbWr1mAXQBcfHYIC+8jkQAsazdoEGiPE+ihiGAYwx04DMBICGjAAUAJSqqGBgAG7+NNHEhiS8AORQcHDJbJExcVFciTwUUcRsEdGx0UqJKhTqUrGGyfU0yWBmZTnRlonWRUpszkA
/* #flow */
type T1 = string;
type T2 = string | number;
type T3 = { [string]: string };
type T4 = { [string]: T2 }
function main(){
var v1: T1 = 'foo';
var v2: T2 = v1;
var v3: T3 = { bar: 'bar' };
var v4: T4 = v3;
}
13: var v4: T4 = v3;
^ Cannot assign `v3` to `v4` because string [1] is incompatible with number [2] in the indexer property. [incompatible-type]
References:
5: type T3 = { [string]: string };
^ [1]
6: type T4 = { [string]: T2 }
^ [2]
Reason
This is normal and expected
If this was allowed, then you would be allowed to do
v4.foo = 1;
var expectAString : string = v3.foo;
And you would get a number even though due to v3's type you should have only got a string.
Solution
Mark the objects as read-only:
type T3 = $ReadOnly<{ [string]: string }>;
type T4 = $ReadOnly<{ [string]: T2 }>;
Flow try link
Since they are read-only this prevents you to actually do v4.foo = 1;.
Note
This is the same for array, see this answer.
Docs
$ReadOnlyArray’s type parameter is covariant while Array’s type parameter is invariant
Invariance, covariance
I want to write a Kusto function with an optional argument. If the argument is not provided, I don't want to do a 'where' statement. Is that possible?
let f = (a:string = "default") {
table1
| where region = a // only do this search if a != default
};
f()
you can use the logical or operator:
let f = (a:string = "default") {
table1
| where a == 'default' or region == a
};
f()
hopefully an easy question.. I've been playing around with Nim and have realised I need to pass a table (dictionary, map, in some other languages), but I can't seem to figure out the syntax for declaring it in doStuff()
import tables
proc doStuff(n:int, t:[int, int]) = # How should I declare 't' here?
if n == 0:
return
t[n] = (n * 10)
echo "length of t = " & ($len(t))
doStuff(n+1, t)
proc main() =
var tbl = initTable[int, int]()
echo "length of tbl = " & ($len(tbl))
tbl[0] = 0
doStuff(5, tbl)
echo "length of tbl = " & ($len(tbl))
main()
The above gets me Error: type expected, but got: [int, int]
Sorry if this is basic, but my Googling hasn't given me an answer yet
Many TIA
You almost got it, it should be like below:
import tables
proc doStuff(n: int, t: var Table[int, int]) =
if n == 0:
return
t[n] = n * 10
echo "length of t = " & $len(t)
doStuff(n + 1, t)
proc main() =
var tbl = initTable[int, int]()
echo "length of tbl = " & $len(tbl)
tbl[0] = 0
doStuff(5, tbl)
echo "length of tbl = " & $len(tbl)
main()
You have to use var Table[int, int] instead of Table[int, int] because you are mutating the tbl variable recursively, so you need to pass by reference instead of by value.
So, I've been fighting with the compiler on a type error.
This code was working as of a couple days ago.
Type misMatch for App level message
App.fs snippets
module App =
type Msg =
| ConnectionPageMsg of ConnectionPage.Msg
| CodeGenPageMsg of CodeGenPage.Msg
//...
let update (msg : Msg) (model : Model) =
match msg with
| ConnectionPageMsg msg ->
let m, cmd = ConnectionPage.update msg model.ConnectionPageModel
{ model with ConnectionPageModel = m }, cmd
| CodeGenPageMsg msg ->
let m, cmd = CodeGenPage.update msg model.CodeGenPageModel
{ model with CodeGenPageModel = m }, cmd
//...
let runner =
Program.mkProgram init update view
|> Program.withConsoleTrace
|> XamarinFormsProgram.run app
I've added explicit aliases and the original error :
Type mismatch. Expecting a
'App.Msg -> App.Model -> App.Model * Cmd<App.Msg>'
but given a
'App.Msg -> App.Model -> App.Model * Cmd<Msg>'
The type 'App.Msg' does not match the type 'Msg'
Became these:
App.fs(50,50): Error FS0001: The type 'PocoGen.Page.ConnectionPage.Msg' does not match the type 'PocoGen.Page.CodeGenPage.Msg' (FS0001) (PocoGen)
App.fs(32,32): Error FS0001: Type mismatch.
Expecting a 'App.Msg -> App.Model -> App.Model * Cmd<App.Msg>'
but given a 'App.Msg -> App.Model -> App.Model * Cmd<Msg>'
The type 'App.Msg' does not match the type 'Msg' (FS0001) (PocoGen)
Other remarks
Right before these errors started appearing I was working on converting a blocking syncronous call to a async command in the ConnectionTestPage and removed the calling code for the cmd hoping that would fix it. (It did not)
ConnectionPage.fs Messages
type Msg =
| UpdateConnectionStringValue of string
| UpdateConnectionStringName of string
| TestConnection
| TestConnectionComplete of Model
| SaveConnectionString of ConnectionStringItem
| UpdateOutput of string
ConnectionPage.fs update
let update (msg : Msg) (m : Model) : Model * Cmd<Msg> =
match msg with
| UpdateConnectionStringValue conStringVal ->
{ m with
ConnectionString =
{ Id = m.ConnectionString.Id
Name = m.ConnectionString.Name
Value = conStringVal }
CurrentFormState =
match hasRequredSaveFields m.ConnectionString with
| false -> MissingConnStrValue
| _ -> Valid }, Cmd.none
| UpdateConnectionStringName conStringName ->
{ m with
ConnectionString =
{ Id = m.ConnectionString.Id
Name = conStringName
Value = m.ConnectionString.Value }
CurrentFormState =
match hasRequredSaveFields m.ConnectionString with
| false -> MissingConnStrValue
| _ -> Valid }, Cmd.none
| UpdateOutput output -> { m with Output = output }, Cmd.none
| TestConnection -> m, Cmd.none
| TestConnectionComplete testResult -> { m with Output = testResult.Output + "\r\n" }, Cmd.none
| SaveConnectionString(_) -> saveConnection m, Cmd.none
I've played with the Fsharp Version (because incidentally I did update to 4.7.2 a bit before getting this error)
The Full Repo:
https://github.com/musicm122/PocoGen_Fsharp/tree/master/PocoGen
The two branches of the match inside App.update have different types. The first branch has type App.Model * Cmd<ConnectionPage.Msg> and the second page has type App.Model * Cmd<CodeGenPage.Msg>.
You can't generally do that. This, for example, wouldn't compile:
let x =
match y with
| true -> 42
| false -> "foo"
What type is x here? Is it int or is it string? Doesn't compute. A match expression has to have all branches of the same type.
To convert Cmd<ConnectionPage.Msg> into a Cmd<App.Msg> (by wrapping the message in ConnectionPageMsg) you can use Cmd.map:
let update (msg : Msg) (model : Model) =
match msg with
| ConnectionPageMsg msg ->
let m, cmd = ConnectionPage.update msg model.ConnectionPageModel
{ model with ConnectionPageModel = m }, Cmd.map ConnectionPageMsg cmd
| CodeGenPageMsg msg ->
let m, cmd = CodeGenPage.update msg model.CodeGenPageModel
{ model with CodeGenPageModel = m }, Cmd.map CodeGenPageMsg cmd
Let's pretend we have the following types:
type Message {
text : Option<string>
}
type Update {
msg : Option<Message>
}
How do I match it in one line, like in C# using null-conditional operator i.e update?.msg?.text ?
Is there a way to do it like this?:
match msg, msg.text with
| Some msg, Some txt -> ...
| None -> ...
because I don't want to be writing 2 nested match expressions.
You have two Record types (missing the "=" in your example). To match some variable of Update type, you could do as follows:
type Message = { text : Option<string> }
type Update = { msg : Option<Message> }
let u = {msg = Some({text = Some "text"})}
//all 3 possible cases
match u with
| {msg = Some({text = Some t})} -> t
| {msg = Some({text = None})} -> ""
| {msg = None} -> ""