JavaCC expects nothing and found nothing - javacc

I'm trying to get to the bottom of a parser problem, but to begin, I'd like to know why this happens:
Encountered "" at line 1, column 1.
Was expecting one of:
Here is the subset of my grammar that causes the problem:
options {
STATIC = false;
DEBUG_PARSER = true;
DEBUG_LOOKAHEAD = true;
LOOKAHEAD = 64;
}
PARSER_BEGIN(MyParser)
package myparser;
public class MyParser {
}
PARSER_END(MyParser)
/* skip whitespace */
SKIP : {
" "
| "\t"
| "\n"
| "\r"
}
/* other symbols */
TOKEN : {
< COMMA: "," >
| < SEMICOLON: ";" >
| < LEFT_PAREN: "(" >
| < RIGHT_PAREN: ")" >
| < LEFT_BRACKET: "[" >
| < RIGHT_BRACKET: "]" >
| < LEFT_BRACE: "{" >
| < RIGHT_BRACE: "}" >
}
/* type specifiers */
TOKEN : {
< TYPE_SPECIFIER:
"void"
| "int"
| "float"
>
}
/* identifiers */
TOKEN [IGNORE_CASE] : {
<IDENTIFIER: ["_","a"-"z"] (["_","a"-"z","0"-"9"])* >
}
SimpleNode Start() : {}
{
/* begin here */
Declaration()
{ return jjtThis; }
}
void Declaration() : {}
{
FunctionPrototype() <SEMICOLON>
| InitDeclaratorList() <SEMICOLON>
}
void FunctionPrototype() : {}
{
FunctionDeclarator() <RIGHT_PAREN>
}
void FunctionDeclarator() : {}
{
FunctionHeaderWithParameters()
| FunctionHeader()
}
void FunctionHeaderWithParameters() : {}
{
/* recursive version:
FunctionHeader() ParameterDeclaration()
FunctionHeaderWithParameters() <COMMA> ParameterDeclaration()
*/
FunctionHeader() ParameterDeclaration() [FunctionHeaderWithParametersPrime()]
}
void FunctionHeaderWithParametersPrime() : {}
{
<COMMA> ParameterDeclaration() [FunctionHeaderWithParametersPrime()]
}
void FunctionHeader() : {}
{
FullySpecifiedType() <IDENTIFIER> <LEFT_PAREN>
}
void FullySpecifiedType() : {}
{
TypeSpecifier()
}
void TypeSpecifier() : {}
{
TypeSpecifierNonArray() [ArraySpecifier()]
}
void ArraySpecifier() : {}
{
/* recursive version:
<LEFT_BRACKET> <RIGHT_BRACKET>
| <LEFT_BRACKET> ConstantExpression() <RIGHT_BRACKET>
| ArraySpecifier() <LEFT_BRACKET> <RIGHT_BRACKET>
| ArraySpecifier() <LEFT_BRACKET> ConstantExpression() <RIGHT_BRACKET>
*/
<LEFT_BRACKET> <RIGHT_BRACKET> [ArraySpecifierPrime()]
}
void ArraySpecifierPrime() : {}
{
<LEFT_BRACKET> <RIGHT_BRACKET> [ArraySpecifierPrime()]
}
void TypeSpecifierNonArray() : {}
{
<TYPE_SPECIFIER>
| TypeName()
}
void TypeName() : {}
{ /* user defined type e.g struct or typedef */
<IDENTIFIER>
}
void ParameterDeclaration() : {}
{
ParameterDeclarator()
| ParameterTypeSpecifier()
}
void ParameterTypeSpecifier() : {}
{
TypeSpecifier()
}
void ParameterDeclarator() : {}
{
TypeSpecifier() <IDENTIFIER>
| TypeSpecifier() <IDENTIFIER> ArraySpecifier()
}
void InitDeclaratorList() : {}
{
/* recursive version:
SingleDeclaration()
| InitDeclaratorList() <COMMA> <IDENTIFIER>
| InitDeclaratorList() <COMMA> <IDENTIFIER> ArraySpecifier()
| InitDeclaratorList() <COMMA> <IDENTIFIER> ArraySpecifier() <EQUAL> Initializer()
| InitDeclaratorList() <COMMA> <IDENTIFIER> <EQUAL> Initializer()
*/
SingleDeclaration() [InitDeclaratorListPrime()]
}
void InitDeclaratorListPrime() : {}
{
<COMMA> <IDENTIFIER> [InitDeclaratorListPrime()]
| <COMMA> <IDENTIFIER> ArraySpecifier() [InitDeclaratorListPrime()]
}
void SingleDeclaration() : {}
{
FullySpecifiedType()
| FullySpecifiedType() <IDENTIFIER>
| FullySpecifiedType() <IDENTIFIER> ArraySpecifier()
}
Function declarations are working fine
void main(int a, int b);
But declaration statements, which go in the function body in the full grammar, are not working
float myvar;
The debug output for the parser and lookahead for this broken example is as follows
Call: Start
Call: Declaration
Call: FunctionPrototype(LOOKING AHEAD...)
Call: FunctionDeclarator(LOOKING AHEAD...)
Call: FunctionHeaderWithParameters(LOOKING AHEAD...)
Call: FunctionHeader(LOOKING AHEAD...)
Call: FullySpecifiedType(LOOKING AHEAD...)
Call: TypeSpecifier(LOOKING AHEAD...)
Call: TypeSpecifierNonArray(LOOKING AHEAD...)
Visited token: <<TYPE_SPECIFIER>: "float" at line 1 column 1>; Expected token: <<TYPE_SPECIFIER>>
Return: TypeSpecifierNonArray(LOOKAHEAD SUCCEEDED)
Call: ArraySpecifier(LOOKING AHEAD...)
Visited token: <<IDENTIFIER>: "myvar" at line 1 column 7>; Expected token: <"[">
Return: ArraySpecifier(LOOKAHEAD FAILED)
Return: TypeSpecifier(LOOKAHEAD SUCCEEDED)
Return: FullySpecifiedType(LOOKAHEAD SUCCEEDED)
Visited token: <<IDENTIFIER>: "myvar" at line 1 column 7>; Expected token: <<IDENTIFIER>>
Visited token: <";" at line 1 column 12>; Expected token: <"(">
Return: FunctionHeader(LOOKAHEAD FAILED)
Return: FunctionHeaderWithParameters(LOOKAHEAD FAILED)
Call: FunctionHeader(LOOKING AHEAD...)
Call: FullySpecifiedType(LOOKING AHEAD...)
Call: TypeSpecifier(LOOKING AHEAD...)
Call: TypeSpecifierNonArray(LOOKING AHEAD...)
Visited token: <<TYPE_SPECIFIER>: "float" at line 1 column 1>; Expected token: <<TYPE_SPECIFIER>>
Return: TypeSpecifierNonArray(LOOKAHEAD SUCCEEDED)
Call: ArraySpecifier(LOOKING AHEAD...)
Visited token: <<IDENTIFIER>: "myvar" at line 1 column 7>; Expected token: <"[">
Return: ArraySpecifier(LOOKAHEAD FAILED)
Return: TypeSpecifier(LOOKAHEAD SUCCEEDED)
Return: FullySpecifiedType(LOOKAHEAD SUCCEEDED)
Visited token: <<IDENTIFIER>: "myvar" at line 1 column 7>; Expected token: <<IDENTIFIER>>
Visited token: <";" at line 1 column 12>; Expected token: <"(">
Return: FunctionHeader(LOOKAHEAD FAILED)
Return: FunctionDeclarator(LOOKAHEAD FAILED)
Return: FunctionPrototype(LOOKAHEAD FAILED)
Call: InitDeclaratorList(LOOKING AHEAD...)
Call: SingleDeclaration(LOOKING AHEAD...)
Call: FullySpecifiedType(LOOKING AHEAD...)
Call: TypeSpecifier(LOOKING AHEAD...)
Call: TypeSpecifierNonArray(LOOKING AHEAD...)
Visited token: <<TYPE_SPECIFIER>: "float" at line 1 column 1>; Expected token: <<TYPE_SPECIFIER>>
Return: TypeSpecifierNonArray(LOOKAHEAD SUCCEEDED)
Call: ArraySpecifier(LOOKING AHEAD...)
Visited token: <<IDENTIFIER>: "myvar" at line 1 column 7>; Expected token: <"[">
Return: ArraySpecifier(LOOKAHEAD FAILED)
Return: TypeSpecifier(LOOKAHEAD SUCCEEDED)
Return: FullySpecifiedType(LOOKAHEAD SUCCEEDED)
Return: SingleDeclaration(LOOKAHEAD SUCCEEDED)
Call: InitDeclaratorListPrime(LOOKING AHEAD...)
Visited token: <<IDENTIFIER>: "myvar" at line 1 column 7>; Expected token: <",">
Visited token: <<IDENTIFIER>: "myvar" at line 1 column 7>; Expected token: <",">
Return: InitDeclaratorListPrime(LOOKAHEAD FAILED)
Return: InitDeclaratorList(LOOKAHEAD SUCCEEDED)
Visited token: <<IDENTIFIER>: "myvar" at line 1 column 7>; Expected token: <";">
Return: Declaration
Return: Start
Encountered "" at line 1, column 1.
Was expecting one of:
The problem seems to be in the SingleDeclaration production, where it expects
FullySpecifiedType()
| FullySpecifiedType() <IDENTIFIER>
where FullySpecifiedType is either a type constant (void, int, float) or another identifier (to facilitate user-defined types).
If I swap these lines around so that it reads
FullySpecifiedType() <IDENTIFIER>
| FullySpecifiedType()
Then it functions as intended. Why does the order make a difference?

First set the LOOAHEAD option to 1, so that JavaCC will warn you about lookahead conflicts.
Your grammar has lookahead conflicts. The JavaCC processor should report these as warnings. You should heed these warnings.
JavaCC, by default, uses the next token of input to make choices. See the documentation and the FAQ for details. Take
void SingleDeclaration() : {}
{
FullySpecifiedType()
| FullySpecifiedType() <IDENTIFIER>
| FullySpecifiedType() <IDENTIFIER> ArraySpecifier()
}
as an example. There is a three-way choice to be made. The choice obviously can't be made on the basis of the kind of the next token, since any token that could start the first choice could also start the second or third.
There are two ways to fix the problem. The best, usually, is to rewrite the grammar.
void SingleDeclaration() : {}
{
FullySpecifiedType()
[
<IDENTIFIER>
[
ArraySpecifier()
]
]
}
The second is to use lookahead specifications.
void SingleDeclaration() : {}
{
LOOKAHEAD(FullySpecifiedType() <IDENTIFIER> "[")
FullySpecifiedType() <IDENTIFIER> ArraySpecifier()
|
LOOKAHEAD(FullySpecifiedType() <IDENTIFIER>)
FullySpecifiedType() <IDENTIFIER>
|
FullySpecifiedType()
}
One more thing, your start production should look like this:
SimpleNode Start() : {}
{
/* begin here */
Declaration() <EOF>
{ return jjtThis; }
}

Related

Updating an array element identified by other fields in the object using jq

Goal
I'd like to add a proxy-url field to the currently active clusters entry of my kubeconfig file. The "active" cluster is identified by the "active" context, which is itself identified by a top-level key current-context. Simplified, the JSON object looks something like:
{
"clusters":[
{
"name":"cluster1",
"field":"field1"
},
{
"name":"cluster2",
"field":"field2"
}
],
"contexts":[
{
"name":"context1",
"context": {
"cluster":"cluster1"
}
},
{
"name":"context2",
"context": {
"cluster":"cluster2"
}
}
],
"current-context": "context1"
}
And I'd like to update the clusters entry for cluster1 from:
{
"name":"cluster1",
"field":"field1"
}
to
{
"name":"cluster1",
"field":"field1",
"proxy-url":"my-url"
}
First attempt
jq '. as $o
| $o."current-context" as $current_context_name
| $o.contexts[] | select(.name == $current_context_name) as $context
| $o.clusters[] | select(.name == $context.context.cluster)
| .proxy_id |= "my-url"'
gives me
{
"name": "cluster1",
"field": "field1",
"proxy_id": "my-url"
}
-- great! But I need the rest of the object too.
Parentheses almost work
With parentheses, I can get the whole object back & add a "proxy-url" field to the active context, but I can't take it one step further to update the active cluster. This filter:
jq '(. as $o
| $o."current-context" as $current_context_name
| $o.contexts[] | select(.name == $current_context_name)
| ."proxy-url")
|= "my-url"'
works mint:
{
"clusters": [...], // omitted for brevity, unchanged
"contexts": [
{
"name": "context1",
"context": {
"cluster": "cluster1"
},
"proxy-url": "my-url" // tada!
},
{...} // omitted for brevity, unchanged
],
"current-context": "context1"
}
Trying to take it one step further (to update the cluster identified by that context, instead):
jq '(. as $o
| $o."current-context" as $current_context_name
| $o.contexts[] | select(.name == $current_context_name) as $context
| $o.clusters[] | select(.name == $context.context.cluster)
| ."proxy-url")
|= "my-url"'
gives me the following error:
jq: error (at <stdin>:26): Invalid path expression near attempt to access element "clusters" of {"clusters":[{"name":"clus...
exit status 5
How can I use the $context.context.cluster result to update the relevant clusters entry? I don't understand why this approach works for adding something to contexts but not to clusters.
Dirty solution
I can kludge together a new clusters entry & merge that with the top-level object:
jq '. as $o
| $o."current-context" as $current_context_name
| $o.contexts[] | select(.name == $current_context_name) as $context
| $o + {"clusters": [($o.clusters[] | select(.name == $context.context.cluster)."proxy-url" |= "my-url")]}
but this feels a bit fragile.
This solution retrieves the active cluster using an INDEX construction, then just sets the new field directly without modifying the context:
jq '
INDEX(.contexts[]; .name)[."current-context"].context.cluster as $cluster
| (.clusters[] | select(.name == $cluster))."proxy-url" = "my-url"
'
{
"clusters": [
{
"name": "cluster1",
"field": "field1",
"proxy-url": "my-url"
},
{
"name": "cluster2",
"field": "field2"
}
],
"contexts": [
{
"name": "context1",
"context": {
"cluster": "cluster1"
}
},
{
"name": "context2",
"context": {
"cluster": "cluster2"
}
}
],
"current-context": "context1"
}
Demo

How can I pattern-match items pulled from a DashMap?

I am trying to pattern match on an enum when getting an item from my dashmap::DashMap. However, it looks like they have a wrapper type over the Entity when they return the data. How can I pattern match over the items then?
use once_cell::sync::Lazy;
use dashmap::DashMap;
enum Entity {
Person { name: String },
Animal { name: String },
}
static ENTITIES: Lazy<DashMap<usize, Entity>> = Lazy::new(|| DashMap::new());
fn main() {
ENTITIES.insert(
0,
Entity::Animal {
name: "pikachu".into(),
},
);
ENTITIES.insert(
1,
Entity::Person {
name: "trainer mike".into(),
},
);
match ENTITIES.get(&0) {
Some(Entity::Animal { name }) => { // compile error here
println!("found animal: {}", name);
}
_ => panic!("did not find person"),
}
}
And the error:
error[E0308]: mismatched types
--> src\lib.rs:__:__
|
| match ENTITIES.get(&0) {
| -------------- this expression has type `Option<dashmap::mapref::one::Ref<'_, usize, Entity>>`
| Some(Entity::Animal { name }) => {
| ^^^^^^^^^^^^^^^^^^^^^^^ expected struct `dashmap::mapref::one::Ref`, found enum `Entity`
|
= note: expected struct `dashmap::mapref::one::Ref<'_, usize, Entity, >`
found enum `Entity`

Flow union type with exact object types gives 'property is missing in [type 1]'

I have a function that accepts a union two disjoint exact types, and constructs a new object. The react documentation indicates that with disjoint exact types, I should be able to infer the type by checking for the existence of a property. However, this doesn't appear to be working -- my else branch indicates that the properties are missing on one of the types.
type Sid = {|
val: string,
id: number
|};
type Entity ={
idOrName: Sid | string,
optionalDescription: ?string
}
const createEntity = (idOrNameAndDescription: Sid | {| name: string, description: string |}): Entity => {
if (idOrNameAndDescription.val) {
return {
idOrName: idOrNameAndDescription,
optionalDescription: null
}
} else {
return {
// These next to lines fail, saying:
// "Flow: Cannot get `idOrNameAndDescription.name` because
// property `name` is missing in `Sid`
idOrName: idOrNameAndDescription.name,
optionalDescription: idOrNameAndDescription.description
}
}
}
See the comment in the else/return statement. The errors given are:
Cannot get idOrNameAndDescription.name because property name is missing in Sid [1].
[1] 60│ const createEntity = (idOrNameAndDescription: Sid | {| name: string, description: string |}): Entity => {
:
65│ }
66│ } else {
67│ return {
68│ idOrName: idOrNameAndDescription.name,
69│ optionalDescription: idOrNameAndDescription.description
70│ }
71│ }
Cannot get idOrNameAndDescription.description because property description is missing in Sid [1].
[1] 60│ const createEntity = (idOrNameAndDescription: Sid | {| name: string, description: string |}): Entity => {
:
66│ } else {
67│ return {
68│ idOrName: idOrNameAndDescription.name,
69│ optionalDescription: idOrNameAndDescription.description
70│ }
71│ }
72│ }
However, as .val was not defined flow should know that it is of the other half of the union and name and description are defined.
I've also tried using if (idOrNameAndDescription.val != null), which makes both of the branches of the if statement invalid as well as if (typeof idOrNameAndDescription.val === 'string'), which results in an even uglier error.
Is this a flow bug or am I missing something?

How to resolve 'Cannot assign because string is incompatible with null or undefined' Flow error?

I'm getting an error from flow, but I'm checking to verify that the error can never happen. How can I tell flow everything is OK?
/* #flow */
type A = {|
test: string;
|}
type B = {|
test: ?string;
|}
function foo(b: B): A {
if (b && b.test) {
return {
test: b.test
};
}
return { test: 'hi' };
}
const test: B = foo({ test: 'a' });
This is the error Flow is giving me.
21: const test: B = foo({ test: 'a' });
^ Cannot assign `foo(...)` to `test` because string [1] is incompatible with null or undefined [2] in property `test`.
References:
4: test: string;
^ [1]
8: test: ?string;
^ [2]
But from the code I'm checking that test can't be null or undefined. So I'm not sure how to go about fixing this.
Live Example Here
/* #flow */
type A = {|
test: string;
|}
type B = {|
test: ?string;
|}
declare var TestA: A;
declare var TestB: B;
TestB = TestA;
// ^ Cannot assign `TestA` to `TestB` because string [1] is incompatible with null or undefined [2] in property `test`
It is because {|test: string;} is not subtype of {|test: ?string;}, we can mutate TestB.test = null, but it also mutate TestA where test should not be null.
{|test: string;} is subtype of {| +test: ?string;}. (+ - read-only)
Syntax error. This is the corrected code I believe.
/* #flow */
type A = {|
test: string;
|}
type B = {|
test: string;
|}
function foo(b: ?B): A {
if (b && b.test) {
return {
test: b.test
};
}
return { test: 'hi' };
}
const test: B = foo({ test: 'a' });

How to range over nested struct in golang?

I am new to Golang:
These are my defined struct:
type Name map[string]Info
type Info struct {
Addresses string `json:"addresses"`
Host map[string]Server `json:"host"`
}
type Server struct {
Ipaddress string `json:"ip"`
Status string `json:"status"`
}
var result Name
after unmarshalling Json i get:
result = [
user1:{
192.168.98.0/26
map[
xx.user1.domain.com:{192.168.98.1 good}
xx.user1.domain.com:{192.168.98.3 good}
xx.user1.domain.com:{192.168.98.4 Bad}
]
}
user2: {
192.168.99.0/26
map[
xx.user2.domain.com:{192.168.99.1 good}
]
}
]
How to range over this Json to get the ipaddress which has a status=="good" for the particular user ?
I am trying to do this way:
for j , _ := range result["user1"].Servers {
if a := result["user1"].Servers[j]); a == "good" {
//Problem is here I am not sure how to further scan the ip and status
//do something
}
}
}
I think you want:
for _ , i := range result {
for _, j := range i.Host {
if j.Status == "good" {
server := j.Ip
}
}
}

Resources