I am trying to accumulate lexer errors when Lexing in run time. I have followed the exact way of achieving this for parser errors as in this answer. But when I try to do this to the Lexer.
class Class2 : IAntlrErrorListener<IToken>
{
public void SyntaxError(IRecognizer recognizer, IToken offendingSymbol, int line, int charPositionInLine, string msg, RecognitionException e)
{
Console.WriteLine("Error in lexer at line " + ":" + e.OffendingToken.Column + e.OffendingToken.Line + e.Message);
}
}
and register this listener as below.
Class2 z = new Class2();
lexer.AddErrorListener(z);
But this gives a error which is unexpected.
Argument 1: cannot convert from 'CSSParserAntlr.Class2' to 'Antlr4.Runtime.IAntlrErrorListener<int>'
and
The best overloaded method match for 'Antlr4.Runtime.Recognizer<int,Antlr4.Runtime.Atn.LexerATNSimulator>.AddErrorListener(Antlr4.Runtime.IAntlrErrorListener<int>)' has some invalid arguments
Please give me some reason why this is happening.
First, the reason you are getting this exception is because you need to declare Class2 as follows:
class Class2 : IAntlrErrorListener<int>
in order to match the class signature of Lexer defined as follows:
public abstract class Lexer : Recognizer<int, LexerATNSimulator>, ITokenSource
The method signature for AddErrorListener is defined in Recognizer to match the Symbol type from the class definition as follows:
public abstract class Recognizer<Symbol, ATNInterpreter> : IRecognizer
This means that Lexer specifies "int" as the "Symbol" when extending Recognizer, and so the AddErrorListener method requires an IAntlrErrorListener of type int.
Now, the real answer to your question: don't write an error listener for a lexer. Errors in the lexing are the fault of the lex grammar, not of the user input. Error listeners are useful for handling bad user input in a Parser. Lexer grammars should be tested for coverage during development - i.e., all possible input will match some token. If you encounter a lex error during development, the default error listener will do just fine.
For more information, see the answer here: ANTLR4 Lexer error reporting (length of offending characters)
Related
The following code throws a MessagingException with message At most one parameter (or expression via method-level #Payload) may be mapped to the payload or Message. Found more than one on method [public abstract java.lang.Integer org.example.PayloadAndGatewayHeader$ArithmeticGateway.add(int,int)].
#MessagingGateway
interface ArithmeticGateway {
#Gateway(requestChannel = "add.input", headers = #GatewayHeader(name = "operand", expression = "#args[1]"))
Integer add(#Payload final int a, final int b);
}
The desired functionality could be achieved with something like:
#MessagingGateway
interface ArithmeticGateway {
#Gateway(requestChannel = "add.input", headers = #GatewayHeader(name = "operand", expression = "#args[1]"))
#Payload("#args[0]")
Integer add(final int a, final int b);
}
Should the first version also work? Nevertheless I believe the error message could be improved.
A sample project can be found here. Please check org.example.PayloadAndGatewayHeader and org.example.PayloadAndGatewayHeaderTest.
EDIT
The purpose of #GatewayHeader was to show why one may want to have additional parameters that will not be part of the payload but I am afraid it created confusion. Here is a more streamlined example:
#MessagingGateway
interface ArithmeticGateway {
#Gateway(requestChannel = "identity.input")
Integer identity(#Payload final int a, final int unused);
}
Shouldn't the unused parameter be ignored since there is already another one that is annotated with #Payload?
You can't mix parameter annotations (which are static) with expressions (which are dynamic) because the static code analysis can't anticipate what the dynamic expression will resolve to at runtime. It is probably unlikely, but there theoretically could be conditions in the expression. In any case, it can't determine at analysis time that the expression will provide a value for #args[1] at runtime (it could, of course for this simple case, but not all cases are this simple).
Use one or the other; use your second approach or
Integer add(#Payload final int a, #Header("operand") final int b);
Can i implement switch statements(by passing string arguments) in java 5 without making use of enums?I tried doing it using hashcode but i got an error
package com.list;
import java.util.Scanner;
public class SwitchDays implements Days {
static final int str = "sunday".hashCode();
public static void main(String[] args) {
Scanner in=new Scanner(System.in);
String day= in.nextLine();
switch (day.hashCode()) {
case str:
System.out.println(day);
break;
default:
break;
}
}
}
str in case str given an error:
case expressions must be constant expressions
Please guide.
The problem is that str is referring to the expression "sunday".hashCode(), which is not a compile time constant expression as described by the JLS:
A constant expression is an expression denoting a value of primitive
type or a String that does not complete abruptly and is composed using
only the following: ... Qualified names (§6.5.6.2) of the form
TypeName . Identifier that refer to constant variables (§4.12.4).
When you check the definition of constant variables:
A constant variable is a final variable of primitive type or type
String that is initialized with a constant expression (§15.28).
Whether a variable is a constant variable or not may have implications
with respect to class initialization (§12.4.1), binary compatibility
(§13.1, §13.4.9), and definite assignment (§16 (Definite Assignment)).
Since "sunday".hashCode() does not meet this requirements, you get the error.
If you would change "sunday".hashCode() to a real compile time constant like 3 it would compile.
The most straight forward solution is to make an enum, ie.
enum Days{
sunday, monday;
}
Then it could be used as:
Day d = Day.valueOf("sunday");
switch(d){
case sunday:
System.out.println("ONE");
break;
case monday:
System.out.println("TWO");
break;
}
I'm using #CompileStatic for the first time, and confused as to how Groovy's map constructors work in this situation.
#CompileStatic
class SomeClass {
Long id
String name
public static void main(String[] args) {
Map map = new HashMap()
map.put("id", 123L)
map.put("name", "test file")
SomeClass someClass1 = new SomeClass(map) // Does not work
SomeClass someClass2 = map as SomeClass // Works
}
}
Given the code above I see the following error when trying to compile
Groovyc: Target constructor for constructor call expression hasn't been set
If #CompileStatic is removed, both constructors work properly.
Can anyone explain why new SomeClass(map) does not compile with #CompileStatic? And a possible addition, why does map as SomeClass still work?
Groovy actually does not give you a "Map-Constructor". The constructors
in your class are what you write down. If there are none (like in your case),
then there is the default c'tor.
But what happens, if you use the so called map c'tor (or rather call it
"object construction by map")? The general approach of groovy is like this:
create a new object using the default c'tor (this is the reason, why the
construction-by-map no longer works, if there would be just e.g.
SomeClass(Long id, String name))
then use the passed down map and apply all values to the properties.
If you disassmble your code (with #CompileDynamic (the default)) you see, that
the construction is handled by CallSite.callConstructor(Object,Object),
which boils down to this this code area.
Now bring in the version of this construction by map, that is more familiar
for the regular groovyist:
SomeClass someClass3 = new SomeClass(id: 42L, name: "Douglas").
With the dynamic version of the code, the disassembly of this looks actually
alot like your code with the map. Groovy creates a map from the param(s) and
sends it off to callConstructor - so this is actually the same code path
taken (minus the implicit map creation).
For now ignore the "cast-case", as it is actually the same for both static and
dynamic: it will be sent to ScriptBytecodeAdapter.asType which basically
gives you the dynamic behaviour in any case.
Now the #CompileStatic case: As you have witnessed, your call with an
explicit map for the c'tor no longer works. This is due to the fact, that
there never was an explicit "map-c'tor" in the first place. The class still
only has its default c'tor and with static compilation groovyc now can just
work with the things that are there (or not if there aren't in this case).
What about new SomeClass(id: 42L, name: "Douglas") then? This still works
with static compilation! The reason for this is, that groovyc unrolls this
for you. As you can see, this simply boils down to def o = new SomeClass();
o.setId(42); o.setName('Douglas'):
new #2 // class SomeClass
dup
invokespecial #53 // Method "<init>":()V
astore_2
ldc2_w #54 // long 42l
dup2
lstore_3
aload_2
lload_3
invokestatic #45 // Method java/lang/Long.valueOf:(J)Ljava/lang/Long;
invokevirtual #59 // Method setId:(Ljava/lang/Long;)V
aconst_null
pop
pop2
ldc #61 // String Douglas
dup
astore 5
aload_2
aload 5
invokevirtual #65 // Method setName:(Ljava/lang/String;)V
As the CompileStatic documentation says:
will actually make sure that the methods which are inferred as being
called will effectively be called at runtime. This annotation turns
the Groovy compiler into a static compiler, where all method calls are
resolved at compile time and the generated bytecode makes sure that
this happens
As a result, a constructor with a Map argument is searched in the static compilation to "resolve it at compile time", but it is not found and thereby there is a compilation error:
Target constructor for constructor call expression hasn't been set
Adding such a constructor solves the issue with the #CompileStatic annotation, since it is resolved at compile time:
import groovy.transform.CompileStatic
#CompileStatic
class SomeClass {
Long id
String name
SomeClass(Map m) {
id = m.id as Long
name = m.name as String
}
public static void main(String[] args) {
Map map = new HashMap()
map.put("id", 123L)
map.put("name", "test file")
SomeClass someClass1 = new SomeClass(map) // Now it works also
SomeClass someClass2 = map as SomeClass // Works
}
}
You can check StaticCompilationVisitor if you want to dig deeper.
Regarding the line
SomeClass someClass2 = map as SomeClass
You are using there the asType() method of Groovy's GDK java.util.Map, so it is therefore solved at runtime even in static compilation:
Coerces this map to the given type, using the map's keys as the public
method names, and values as the implementation. Typically the value
would be a closure which behaves like the method implementation.
I have a list of KeyValuePairs. I normally would use ToDictionary.
However I just noted that the error message (shown below) has something about explicit cast, which implies I can actually cast the list to Dictionary<...>. How can I do this?
Cannot implicitly convert type 'System.Linq.IOrderedEnumerable<System.Collections.Generic.KeyValuePair<int,string>>' to 'System.Collections.Generic.Dictionary<int, string>'. An explicit conversion exists (are you missing a cast?)
Sample code:
Dictionary<int, string> d = new Dictionary<int, string>() {
{3, "C"},
{2, "B"},
{1, "A"},
};
var s = d.OrderBy(i => i.Value);
d = s;
Implies I can actually cast list to dictionary
Well, it implies that the cast would be valid at compile-time. It doesn't mean it will work at execution time.
It's possible that this code could work:
IOrderedEnumerable<KeyValuePair<string, string>> pairs = GetPairs();
Dictionary<string, string> dictionary = (Dictionary<string, string>) pairs;
... but only if the value returned by GetPairs() were a class derived from Dictionary<,> which also implemented IOrderedEnumerable<KeyValuePair<string, string>>. It's very unlikely that that's actually the case in normal code. The compiler can't stop you from trying, but it won't end well. (In particular, if you do it with the code in your question and with standard LINQ to Objects, it will definitely fail at execution time.)
You should stick with ToDictionary... although you should also be aware that you'll lose the ordering, so there's no point in ordering it to start with.
To show this with the code in your question:
Dictionary<int, string> d = new Dictionary<int, string>() {
{3, "C"},
{2, "B"},
{1, "A"},
};
var s = d.OrderBy(i => i.Value);
d = (Dictionary<int, string>) s;
That compiles, but fails at execution time as predicted:
Unhandled Exception: System.InvalidCastException: Unable to cast object of type 'System.Linq.OrderedEnumerable`2[System.Collections.Generic.KeyValuePair`2[System.Int32,System.String],System.String]' to type 'System.Collections.Generic.Dictionary`2[System.Int32,System.String]'.
at Test.Main()
As a bit of background, you can always cast from any interface type to a non-sealed class ("target"), even if that type doesn't implement the interface, because it's possible for another class derived from "target" to implement the interface.
From section 6.2.4 of the C# 5 specification:
The explicit reference conversions are:
...
From any class-type S to any interface-type T, provided S is not sealed and provided S does not implement T.
...
(The case where S does implement T is covered by implicit reference conversions.)
If you try to implicitly convert a value and there's no implicit conversion available, but there's an explicit conversion available, the compiler will give you the warning in your question. That means you can fix the compiler-error with a cast, but you need to be aware of the possibility of it failing at execution time.
Here's an example:
using System;
class Test
{
static void Main()
{
IFormattable x = GetObject();
}
static object GetObject()
{
return DateTime.Now.Second >= 30 ? new object() : 100;
}
}
Error message:
Test.cs(7,26): error CS0266: Cannot implicitly convert type 'object' to
'System.IFormattable'. An explicit conversion exists (are you missing a cast?)
So we can add a cast:
IFormattable x = (IFormattable) GetObject();
At this point, the code will work about half the time - the other half, it'll throw an exception.
I am implementing a smart pointer class using generics and I wanted to force users of this class to properly construct the smart pointer using syntax such as
MyReference<TestCls>(mytest3))
or
MyReference<TestCls> mytest4(new TestCls());
so I have used the explicit keyword on the CTOR, to prevent this:
MyReference aRef = NULL;
However due to unfortunate circumstances beyond my control, I am working on code that is compiled using the ancient MSVC++ 4.1 compiler. I get the following errors when I include the explicit keyword:
MyReference.h(49) : error C2501: 'explicit' : missing decl-specifiers
MyReference.h(51) : error C2143: syntax error : missing ';' before ''
MyReference.h(52) : error C2238: unexpected token(s) preceding ':'
MyReference.h(52) : error C2059: syntax error : 'int constant'
When I add a #define explicit those errors disappear.
This was a hack on my part, just to get the compiler to ignore the keyword. I'm guessing that this means that explicit is not supported by yon olde compiler.
Can someone confirm this and is there anyone out there with knowledge of a workaround solution for this?
Merci Beaucoups,
Dennis.
This site has a workaround for this, namely:
Unfortunately, older compilers may not
support the use of "explicit", which
could be a headache. If you're stuck
working with an out-of-date compiler
and can't get one that has better
support for the C++ standard, your
best solution may be to take advantage
of the fact that only a single
implicit conversion will take place
for a given value. You can exploit
this by using an intermediate class
that implicitly creates an object of
each type, and then have your main
class implicitly create objects from
that class:
class proxy
{
public:
proxy(int x) : x(x) {} ;
getValue() { return x; }
private:
int x;
};
class String
{
// this will be equivalent of explicit
String(proxy x) { /* create a string using x.getValue(); */ }
}