I am implementing a grammar with three sections. In the first section I declare components with their interfaces, for instance Component A with interfaces interface_1, interface_2. In the third section I declare some restrictions, for instance component A can acces component B through interface XXXX. When I try to cross-reference the interfaces of a component I get the error "Couldn't resolve reference to ProbeInterface 'interface_1'"?.
I tried several examples from internet but none of them works to my case.
This is part of my grammar:
ArchitectureDefinition:
'Abstractions' '{' abstractions += DSLAbstraction+ '}'
'Compositions' '{' compositions += DSLComposition* '}'
'Restrictions' '{' restrictions += DSLRestriction* '}'
;
DSLComposition:
DSLProbe|DSLSensor
;
DSLRestriction:
'sensor' t=[DSLSensor] 'must-access-probe' type = [DSLProbe] 'through-interface' probeinterface=[ProbeInterface] ';'
;
DSLSensor:
'Sensor' name=ID ';'
;
DSLProbe:
'Probe' name=ID ('with-interface' probeinterface=ProbeInterface)? ';'
;
ProbeInterface :
name+=ID (',' name+=ID)*
;
And the implementation:
Abstractions
{
Sensor sensor_1 ;
Probe probe_1 with-interface interface_1, interface_2;
}
Compositions{}
Restrictions
{
sensor sensor_1 must-access-probe probe_1 through-interface
interface_1;
}
I expect that interface_1 or interface_2 can be referenced by the grammar.
Thanks.
the grammar you posted is incomplete
the way you define the interfaces is really bad.
default naming works only with single valued name attributes
ProbeInterface :
name+=ID (',' name+=ID)*
;
better
DSLProbe:
'Probe' name=ID ('with-interface' probeinterfaces+=ProbeInterface ("," probeinterfaces+=ProbeInterface)*)? ';'
;
ProbeInterface :
name=ID
;
it looks like the qualified name of a Interface is
<probename>.<interfacename>
you either have to adapt the name provider
or the grammar and model to use qualiedname ref=[Thing|FQN] with FQN: ID ("." ID)*;
or you implement scoping properly which is what you want to do likely in your case since you want to restrict the inferfaces for specific probes
here is a sample
override getScope(EObject context, EReference reference) {
if (reference === MyDslPackage.Literals.DSL_RESTRICTION__PROBEINTERFACE) {
if (context instanceof DSLRestriction) {
val probe = context.type
return Scopes.scopeFor(probe.probeinterfaces)
}
}
super.getScope(context, reference)
}
I have a fortran subroutine, FortranShake, and a C++ main function, HandShakingTest.cpp.
I'm trying to call a fortran subroutine from CLR C++.
I'm getting two batches of errors. Let's call them ERROR(1) and ERROR(2). I'd really appreciate if you could help me understand why these errors are happening.
When I try to compile with the following:
cl /clr HandShakingTest.cpp
I get the following ERROR(1):
HandShakingTest.obj : error LNK2028: unresolved token (0A00030A) "extern "C" void __c
ecl FortranShake(int &)" (?FortranShake##$$J0YAXAAH#Z) referenced in function "int __
lrcall main(cli::array<class System::String ^ >^)" (?main##$$HYMHP$01AP$AAVString#Sys
em###Z)
HandShakingTest.obj : error LNK2019: unresolved external symbol "extern "C" void __cd
cl FortranShake(int &)" (?FortranShake##$$J0YAXAAH#Z) referenced in function "int __c
rcall main(cli::array<class System::String ^ >^)" (?main##$$HYMHP$01AP$AAVString#Syst
m###Z)
HandShakingTest.exe : fatal error LNK1120: 2 unresolved externals
I then used the following commands to compile instead:
ifort /c FortranShake.f //Which compiles fine
cl /c /clr HandShakingTest.cpp //compiles fine
cl /o test HandShakingTest.obj FortranShake.obj //ERROR(2) occurs
ERROR(2) consists of:
MSVCRT.lib(ti_inst.obj) : error LNK2005: "private: __thiscall type_info::type_info(cla
ss type_info const &)" (??0type_info##AAE#ABV0##Z) already defined in LIBCMT.lib(typin
fo.obj)
MSVCRT.lib(ti_inst.obj) : error LNK2005: "private: class type_info & __thiscall type_i
nfo::operator=(class type_info const &)" (??4type_info##AAEAAV0#ABV0##Z) already defin
ed in LIBCMT.lib(typinfo.obj)
MSVCRT.lib(merr.obj) : error LNK2005: __matherr already defined in LIBCMT.lib(_matherr
_.obj)
LINK : warning LNK4098: defaultlib 'MSVCRT' conflicts with use of other libs; use /NOD
EFAULTLIB:library
HandShakingTest.obj : error LNK2028: unresolved token (0A00030A) "extern "C" void __cd
ecl FortranShake(int &)" (?FortranShake##$$J0YAXAAH#Z) referenced in function "int __c
lrcall main(cli::array<class System::String ^ >^)" (?main##$$HYMHP$01AP$AAVString#Syst
em###Z)
HandShakingTest.obj : error LNK2019: unresolved external symbol "extern "C" void __cde
cl FortranShake(int &)" (?FortranShake##$$J0YAXAAH#Z) referenced in function "int __cl
rcall main(cli::array<class System::String ^ >^)" (?main##$$HYMHP$01AP$AAVString#Syste
m###Z)
libifcoremt.lib(for_main.obj) : error LNK2019: unresolved external symbol _MAIN__ refe
renced in function _main
test.exe : fatal error LNK1120: 3 unresolved externals
Here's the HandShakingTest.cpp:
#include "stdio.h"
#include <stdlib.h>
#include <Windows.h>
#using <System.DLL>
#using <System.Windows.Forms.DLL>
using namespace std;
using namespace System;
using namespace System::IO;
using namespace System::Diagnostics;
using namespace System::ComponentModel;
using namespace System::Collections;
using namespace System::Windows::Forms;
extern "C" {void FortranShake(int&);}
int main(array<System::String ^> ^args)
{
Process^ testHand = gcnew Process();
testHand->StartInfo->UseShellExecute = false;
testHand->StartInfo->RedirectStandardInput = true;
testHand->StartInfo->RedirectStandardOutput = true;
testHand->StartInfo->ErrorDialog = true;
int numDebug = 0;
String^ returnedDebug = "Nothing";
FortranShake(numDebug);
StreamReader^ FromHandProcess = testHand->StandardOutput;
StreamWriter^ ToHandProcess = testHand->StandardInput;
String^ Line;
Line = FromHandProcess ->ReadLine();
if (Line->Equals("Enter Hand") )
{
Console::WriteLine(L"Hand Started!");
}
ToHandProcess ->WriteLine(numDebug.ToString());
returnedDebug = FromHandProcess ->ReadLine();
MessageBox::Show(returnedDebug);
return 0;
}
Here is the Fortran Subroutine:
SUBROUTINE FortranShake(GP_DEBUG)
IMPLICIT DOUBLE PRECISION (A-H,O-Z)
INN = 5
WRITE(06,'(a)') 'Enter Hand'
READ(INN,*) GP_DEBUG
GP_DEBUG = GP_DEBUG + 55
WRITE(06,*) GP_DEBUG
RETURN
END
Your first error is actually a linker error - without the /c command line switch you are compiling and linking in one step. No Fortran code or object code has been provided.
Your second error is because:
You have specified (through omission) mismatching runtime libraries for the C++ and the Fortran. You need to decide whether you want to use static linking (the default for the current (as of today, but not necessarily as of next month...) release of Intel Fortran on windows) or dynamic linking (the default for the MS C++ compiler). Perhaps add /MD to the ifort command line, which specifies dynamic linking.
Without compiler options or directives to the contrary, the equivalent identifier for the Fortran procedure in C code as generated by that Fortran compiler is an upper case variant of the Fortran procedure's name - i.e. in the C++ code call the procedure FORTRANSHAKE. If you can write your Fortran code to the F2003 standard, you should use the C interoperability features of that language (BIND(C,...)) to control the C binding name of the Fortran procedure and ensure calling conventions, etc align.
The dummy argument of the Fortran subroutine has the DOUBLE PRECISION type specifier, which is equivalent to double in the C++ for this combination of compilers, not int. Again, F2003 introduces features that can make this alignment of argument types more robust.
I'm very confused about an error I'm getting. I have the following code:
In View1.m I make this call:
[iconView addIconWithType:IconTypeStandard];
IconView.h
typedef enum {
IconTypeStandard = 0,
IconTypeNew = 1,
} IconType;
-(void)addIconWithType:(IconType)iconType;
IconView.m
-(void)addIconWithType:(IconType)iconType {
...
}
Icon.h
#import "IconView.h"
#interface Icon : UIView {
}
-(Icon *)initWithFrame:(CGRect)frame;
-(void)type:(IconType)iconType;
That line is causing an error of 'Expected ')' before 'IconType'', but i have no idea why?
Icon.m
-(void)type:(IconType)iconType {
...
}
I am guessing there is a cyclical inclusion. Icon.h refers to IconView.h and vice versa. Since the typedef comes after the import statement in Icon.h it is raising the error as it can't find IconType yet.
You should probably declare #class IconView; and move the #import "IconView.h" to Icon.m.
You have a trailing comma in your enum
IconTypeNew = 1, // remove the comma
I have a problem while building AST in ANTLR (I'm using ANTLR 3.2, ANTLRWorks 1.4).
This is my grammar:
classDeclaration
:
(
'class' n=IDENTIFIER ('extends' e=IDENTIFIER)?
'{'
…
'}'
)
-> ^(CLASSDECLARATION ^(NAME $n) ^(EXTENDS $e)
;
The problem occurs with optional part of the class — ('extends' e=IDENTIFIER)?.
So the grammar works good with this class declaration:
class Test1 extends AbstractTest1 {
…
}
And fails when I exclude extends part, as follows:
class Test2 {
…
}
ANTLR just stops before this fragment and gives this exception in console:
javax.swing.text.BadLocationException: Position not represented by view
How can I point to ANTLR to handle rewrite rule ^(EXTENDS $e) as optional?
Got the problem solved. Nothing tricky, just had to use common RegExp syntax:
^(EXTENDS $e)?
----- hello, world 2.cpp -----
// Hello, World 2.cpp : main project file.
#include "stdafx.h"
#include "hello.h"
#include <string>
using namespace System;
using namespace std;
int main(array<System::String ^> ^args)
{
hello hi = new hello("Bob", "Blacksmith");
Console::WriteLine(L"Hello, " + hi.getName + "!");
return 0;
}
----- hello.h -----
#include <string>
using namespace std;
#ifndef HELLO_H
#define HELLO_H
class hello
{
private:
string _fname;
string _lname;
//hello() { } // private default constructor
public:
hello(string fname, string lname);
void SetName(string fname, string lname);
string GetName();
};
#endif
----- hello.cpp -----
#include "stdafx.h"
#include "hello.h"
#include <string>
using namespace std;
hello::hello(string fname, string lname)
{
SetName(fname, lname);
}
void hello::SetName(string fname, string lname)
{
_fname = fname;
_lname = lname;
}
string hello::getName()
{
return _fname + _lname;
}
----- The errors -----
------ Build started: Project: Hello, World 2, Configuration: Debug Win32 ------
Hello, World 2.cpp
Hello, World 2.cpp(12): error C2440: 'initializing' : cannot convert from 'hello *' to 'hello'
No constructor could take the source type, or constructor overload resolution was ambiguous
Hello, World 2.cpp(13): error C2039: 'getName' : is not a member of 'hello'
\documents\visual studio 2010\projects\cpp\hello, world 2\hello, world 2\hello.h(8) : see declaration of 'hello'
hello.cpp
hello.cpp(17): error C2039: 'getName' : is not a member of 'hello'
\documents\visual studio 2010\projects\cpp\hello, world 2\hello, world 2\hello.h(8) : see declaration of 'hello'
hello.cpp(19): error C2065: '_fname' : undeclared identifier
hello.cpp(19): error C2065: '_lname' : undeclared identifier
Generating Code...
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Error messages tell you exactly where and what the problems are, though they can be a bit intimidating at first. Maybe I can help demystify them a bit:
Hello, World 2.cpp(12): error C2440: 'initializing' : cannot convert from 'hello *' to 'hello'
This means that on line 12 in Hello, World 2.cpp, you're trying to put a pointer to hello (the return from new) inside hi which is not a pointer type. Since you don't need a dynamically allocated object here, just drop the new.
In situations where you do need a dynamically allocated object, you would change the hi variable to hello * and add a corresponding delete.
Hello, World 2.cpp(13): error C2039: 'getName' : is not a member of 'hello'
C++ is case sensitive. In one file you have GetName, in the other you have getName. Pick one.
hello.cpp(19): error C2065: '_fname' : undeclared identifier
hello.cpp(19): error C2065: '_lname' : undeclared identifier
Line 19 of hello.cpp is the definition of the lower case getName. Since getName wasn't declared in the class (see previous error), the compiler has no idea what _fname or _lname are. These errors will go away once the original problems are solved.
Edit
See #Sergey's answer for some other more general observations of things to fix.
The new keyword creates a pointer - if you do it this way, 'hi' should be declared as hello*, or you should reqrite the declaration as:
hello hi(...);
The second error is just due to case sensitivity (getName, GetName).
hello hi = new hello("William", "Dyson");
Must be
hello* hi = new hello(...);
Or
hello hi("William", "Dyson"); ;
Console::WriteLine(L"Hello, " + hi.getName + "!");
Must be
Console::WriteLine(L"Hello, " + hi.getName() + "!");
There may be other failures but i have to go now.
There are several errors.
File names with whitespaces. Not critical, but can lead to problems
Console::WriteLine(L"Hello, " + hi.getName + "!");
this should be something like this:
string s("Hello, ");
s += hi->getName();
s += "!"
Console::WriteLine(s);
delete objects allocated with new: delete hi;
string hello::getName() should be string hello::GetName()
Never use the use namespace ... in header files
Include other files within guard block
If you allocate something with new you have to call delete after you don't need it anymore.
In case you want to use the garbage collector the clean up for you you have to declare the class as ref class hello and then instantiate it with:
hello^ hi = gcnew hello(...);
Some comments that undoubtedly will be posted before I'm finished writing this:
Put you public members first
the namespace System implies Managed C++, if you don't know what that is and think you are using plain C++, please read about printf and std::cout.
The line
hello hi = new hello("William", "Dyson");
should read
hello hi("William", "Dyson"); or hello* hi = new hello("William", "Dyson");
The first creates an object on the stack (which will be automatically destructed as it goes out of scope. The second creates a pointer to an object on the heap, which you will have to delete before the pointer goes out of scope (after you've finished with it)
about hello::getName(): you have typos with regards to capitalization (getname vs getName) and it should be declared like this (in header and accordingly in the source file):
const string getName() const;
The first const is optional, but I like it that way, the last one lets you call this function from a const hello object, and tells the reader that the function does not modify the object.
You should pass string by reference (here is a correcter constructor):
hello( const string &fname, const string& lname);
Sources and headers should have names without spaces (or special characters) in them, this will be problematic for UNIX<->Windows if you're not careful.
That's all I can see right now.