ANTLR3 c target: when rule fail, action still execute, i can't understand - antlr

when rule fail, action still execute, why?
There is my test:
grammar Test;
options{
language = C;
}
#parser::includes
{
#include <iostream>
}
#lexer::includes
{
#include <iostream>
}
rScript
: INT LR RR{std::cout << "Action Run...\n";};
INT :
('0'..'9')+;
LR : '{';
RR : '}';
main fun:
int main()
{
char teststr1[] = "111dd}";
pANTLR3_INPUT_STREAM input;
input = antlr3StringStreamNew((pANTLR3_UINT8)teststr1, ANTLR3_ENC_8BIT, sizeof(teststr1) - 1, (pANTLR3_UINT8)"-memory-");
pTestLexer Lex = TestLexerNew(input);
pANTLR3_COMMON_TOKEN_STREAM tstream = antlr3CommonTokenStreamSourceNew(
ANTLR3_SIZE_HINT, TOKENSOURCE(Lex));
pTestParser psr = TestParserNew(tstream);
psr->rScript(psr);
int ParserErrorCount = psr->pParser->rec->state->errorCount;
int LexerErrorCount = Lex->pLexer->rec->state->errorCount;
std::cout << "Parser Error Count: " << ParserErrorCount << "\n";
std::cout << "Lexer Error Count: " << LexerErrorCount << "\n";
getchar();
return 0;
}
Output:
-memory-(1) : lexer error 3 :
at offset 4, near 'd' :
dd}
-memory-(1) : lexer error 3 :
at offset 5, near 'd' :
d}
-memory-(1) : error 10 : org.antlr.runtime.MissingTokenException, at offset 5
near [Index: 0 (Start: 0-Stop: 0) ='<missing LR>', type<5> Line: 1 LinePos:5]
: Missing LR
Action Run...
Parser Error Count: 1
Lexer Error Count: 2
My question has two:
I can't understand, why the rule match fail, but the action still run?
How to exit parser when first error catch(lexer or parser error), i have no idea for this, please help.
thanks in advance.

Related

GDAL VSIS3 and GetRasterBand

I'm trying to access some Landsat data from S3 without making local copies of the files. As a test I wanted to run a simple GetRasterBand on the file but I'm not sure how to go about treating a VSILFILE as a GDALDataset without downloading the file.
GDAL API guide states VSILFILE "cannot be used with any functions other than the "VSI*L" family of functions. They aren't "real" FILE objects."
Snip of my code :
VSILFILE *poVs3Dataset;
//GDALDataset *poDataset;
GDALRasterBand *poBand;
char * path = (char *)"/vsis3/landsat-pds/c1/L8/139/045/LC08_L1TP_139045_20170304_20170316_01_T1/LC08_L1TP_139045_20170304_20170316_01_T1_B1.TIF";
GDALAllRegister();
VSIInstallS3FileHandler();
CPLSetConfigOption( "AWS_ACCESS_KEY_ID", "XXX" );
CPLSetConfigOption( "AWS_SECRET_ACCESS_KEY", "XXX" );
poVs3Dataset = VSIFOpenL(path, "r");
poBand = poVs3Dataset->GetRasterBand( 1 );
Which ultimately and understandably fails
g++ -g -L/usr/local/lib -lgdal stats.cpp
error: ‘VSILFILE’ has no member named ‘GetRasterBand’
Are there any good C++ examples out there I could work through?
Thanks!
Setting my environment variables prior to calling the executable seemed to help:
$> env AWS_ACCESS_KEY_ID=xxx AWS_SECRET_ACCESS_KEY=xxx ./a.out /vsis3/landsat-pds/c1/L8/139/045/LC08_L1TP_139045_20170304_20170316_01_T1/LC08_L1TP_139045_20170304_20170316_01_T1_B1.TIF
This is now my test code to prove to myself I can access with both GDALOpenEx & VSIFOpenExL which works in case it helps someone else:
VSILFILE *fpL;
GDALDataset *poDataset;
GDALRasterBand *poBand;
char * path = (char *)"/vsis3/landsat-pds/c1/L8/139/045/LC08_L1TP_139045_20170304_20170316_01_T1/LC08_L1TP_139045_20170304_20170316_01_T1_B1.TIF";
VSIStatBufL sStat;
const char* const apszAllowedDrivers[] = { "GTiff", NULL };
GDALAllRegister();
poDataset = reinterpret_cast<GDALDataset*>(GDALOpenEx(path, GDAL_OF_READONLY | GDAL_OF_RASTER | GDAL_OF_VERBOSE_ERROR, NULL, NULL, NULL));
if( poDataset == NULL )
{
std::cout << "Couldn't open " << std::endl;
}
poBand = poDataset->GetRasterBand( 1 );
int nXSize = poBand->GetXSize();
int nYSize = poBand->GetYSize();
std::cout << "nXSize : " << nXSize << std::endl;
std::cout << "nYSize : " << nYSize << std::endl;
fpL = VSIFOpenExL(path, "rb", 1);
if( fpL != NULL )
{
....
works!!!

ANTLR4: Unexpected behavior that I can't understand

I'm very new to ANTLR4 and am trying to build my own language. So my grammar starts at
program: <EOF> | statement | functionDef | statement program | functionDef program;
and my statement is
statement: selectionStatement | compoundStatement | ...;
and
selectionStatement
: If LeftParen expression RightParen compoundStatement (Else compoundStatement)?
| Switch LeftParen expression RightParen compoundStatement
;
compoundStatement
: LeftBrace statement* RightBrace;
Now the problem is, that when I test a piece of code against selectionStatement or statement it passes the test, but when I test it against program it fails to recognize. Can anyone help me on this? Thank you very much
edit: the code I use to test is the following:
if (x == 2) {}
It passes the test against selectionStatement and statement but fails at program. It appears that program only accepts if...else
if (x == 2) {} else {}
Edit 2:
The error message I received was
<unknown>: Incorrect error: no viable alternative at input 'if(x==2){}'
Cannot answer your question given the incomplete information provided: the statement rule is partial and the compoundStatement rule is missing.
Nonetheless, there are two techniques you should be using to answer this kind of question yourself (in addition to unit tests).
First, ensure that the lexer is working as expected. This answer shows how to dump the token stream directly.
Second, use a custom ErrorListener to provide a meaningful/detailed description of its parse path to every encountered error. An example:
public class JavaErrorListener extends BaseErrorListener {
public int lastError = -1;
#Override
public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine,
String msg, RecognitionException e) {
Parser parser = (Parser) recognizer;
String name = parser.getSourceName();
TokenStream tokens = parser.getInputStream();
Token offSymbol = (Token) offendingSymbol;
int thisError = offSymbol.getTokenIndex();
if (offSymbol.getType() == -1 && thisError == tokens.size() - 1) {
Log.debug(this, name + ": Incorrect error: " + msg);
return;
}
String offSymName = JavaLexer.VOCABULARY.getSymbolicName(offSymbol.getType());
List<String> stack = parser.getRuleInvocationStack();
// Collections.reverse(stack);
Log.error(this, name);
Log.error(this, "Rule stack: " + stack);
Log.error(this, "At line " + line + ":" + charPositionInLine + " at " + offSymName + ": " + msg);
if (thisError > lastError + 10) {
lastError = thisError - 10;
}
for (int idx = lastError + 1; idx <= thisError; idx++) {
Token token = tokens.get(idx);
if (token.getChannel() != Token.HIDDEN_CHANNEL) Log.error(this, token.toString());
}
lastError = thisError;
}
}
Note: adjust the Log statements to whatever logging package you are using.
Finally, Antlr doesn't do 'weird' things - just things that you don't understand.

wcout function does not print a french character

I am using the wcin in order to store a single character in a wchar_t. Then I try to print it with a wcout call and the french character 'é' : but I can't see it at my console.
My compiler is g++ 4.5.4 and my OS is Ubuntu 12.10 64 bits.
Here is my attempt (wideChars.cpp) :
#include <iostream>
int main(){
using namespace std;
wchar_t aChar;
cout << "Enter your char : ";
wcin >> aChar;
wcout << L"You entered " << aChar << L" .\n";
return 0;
}
When I lauch the programm :
$ ./wideChars
Enter your char : é
You entered .
So, what's wrong with this code ?
First, add some error checking. Test what does wcin.good() return after the input and what does wcout.good() return after the "You entered" print? I suspect one of those will return false.
What are your LANG and LC_* environment variables set to?
Then try to fix this by adding this at the top of your main(): wcin.imbue(std::locale("")); wcout.imbue(std::locale(""));
I do not have my Ubuntu at hand right now, so I am flying blind here and mostly guessing.
UPDATE
If the above suggestion does not help then try to construct locale like this and imbue() this locale instead.
std::locale loc (
std::locale (),
new std::codecvt_byname<wchar_t, char, std::mbstate_t>("")));
UPDATE 2
Here is what works for me. The key is to set the C locale as well. IMHO, this is a bug in GNU C++ standard library implementation. Unless I am mistaken, setting std::locale::global(""); should also set the C library locale.
#include <iostream>
#include <locale>
#include <clocale>
#define DUMP(x) do { std::wcerr << #x ": " << x << "\n"; } while (0)
int main(){
using namespace std;
std::locale loc ("");
std::locale::global (loc);
DUMP(std::setlocale(LC_ALL, NULL));
DUMP(std::setlocale(LC_ALL, ""));
wcin.imbue (loc);
DUMP (wcin.good());
wchar_t aChar = 0;
wcin >> aChar;
DUMP (wcin.good());
DUMP ((int)aChar);
wcout << L"You entered " << aChar << L" .\n";
return 0;
}
UPDATE 3
I am confused, now I cannot reproduce it again and setting std::locale::global(loc); seems to do the right thing wrt/ the C locale as well.

OpenCL, simple vector addition but wrong output for large input

So, after spending hours reading and understanding I have finally made my first OpenCL program that actually does something, which is it adds two vectors and outputs to a file.
#include <iostream>
#include <vector>
#include <cstdlib>
#include <string>
#include <fstream>
#define __CL_ENABLE_EXCEPTIONS
#include <CL/cl.hpp>
int main(int argc, char *argv[])
{
try
{
// get platforms, devices and display their info.
std::vector<cl::Platform> platforms;
cl::Platform::get(&platforms);
std::vector<cl::Platform>::iterator i=platforms.begin();
std::cout<<"OpenCL \tPlatform : "<<i->getInfo<CL_PLATFORM_NAME>()<<std::endl;
std::cout<<"\tVendor: "<<i->getInfo<CL_PLATFORM_VENDOR>()<<std::endl;
std::cout<<"\tVersion : "<<i->getInfo<CL_PLATFORM_VERSION>()<<std::endl;
std::cout<<"\tExtensions : "<<i->getInfo<CL_PLATFORM_EXTENSIONS>()<<std::endl;
// get devices
std::vector<cl::Device> devices;
i->getDevices(CL_DEVICE_TYPE_ALL,&devices);
int o=99;
std::cout<<"\n\n";
// iterate over available devices
for(std::vector<cl::Device>::iterator j=devices.begin(); j!=devices.end(); j++)
{
std::cout<<"\tOpenCL\tDevice : " << j->getInfo<CL_DEVICE_NAME>()<<std::endl;
std::cout<<"\t\t Type : " << j->getInfo<CL_DEVICE_TYPE>()<<std::endl;
std::cout<<"\t\t Vendor : " << j->getInfo<CL_DEVICE_VENDOR>()<<std::endl;
std::cout<<"\t\t Driver : " << j->getInfo<CL_DRIVER_VERSION>()<<std::endl;
std::cout<<"\t\t Global Mem : " << j->getInfo<CL_DEVICE_GLOBAL_MEM_SIZE>()/(1024*1024)<<" MBytes"<<std::endl;
std::cout<<"\t\t Local Mem : " << j->getInfo<CL_DEVICE_LOCAL_MEM_SIZE>()/1024<<" KBbytes"<<std::endl;
std::cout<<"\t\t Compute Unit : " << j->getInfo<CL_DEVICE_MAX_COMPUTE_UNITS>()<<std::endl;
std::cout<<"\t\t Clock Rate : " << j->getInfo<CL_DEVICE_MAX_CLOCK_FREQUENCY>()<<" MHz"<<std::endl;
}
std::cout<<"\n\n\n";
//MAIN CODE BEGINS HERE
//get Kernel
std::ifstream ifs("vector_add_kernel.cl");
std::string kernelSource((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
std::cout<<kernelSource;
//Create context, select device and command queue.
cl::Context context(devices);
cl::Device &device=devices.front();
cl::CommandQueue cmdqueue(context,device);
// Generate Source vector and push the kernel source in it.
cl::Program::Sources sourceCode;
sourceCode.push_back(std::make_pair(kernelSource.c_str(), kernelSource.size()));
//Generate program using sourceCode
cl::Program program=cl::Program(context, sourceCode);
//Build program..
try
{
program.build(devices);
}
catch(cl::Error &err)
{
std::cerr<<"Building failed, "<<err.what()<<"("<<err.err()<<")"
<<"\nRetrieving build log"
<<"\n Build Log Follows \n"
<<program.getBuildInfo<CL_PROGRAM_BUILD_LOG>(devices.front());
}
//Declare and initialize vectors
std::vector<cl_float>B(993448,1.3);
std::vector<cl_float>C(993448,1.3);
std::vector<cl_float>A(993448,1.3);
cl_int N=A.size();
//Declare and intialize proper work group size and global size. Global size raised to the nearest multiple of workGroupSize.
int workGroupSize=128;
int GlobalSize;
if(N%workGroupSize) GlobalSize=N - N%workGroupSize + workGroupSize;
else GlobalSize=N;
//Declare buffers.
cl::Buffer vecA(context, CL_MEM_READ_WRITE, sizeof(cl_float)*N);
cl::Buffer vecB(context, CL_MEM_READ_ONLY , (B.size())*sizeof(cl_float));
cl::Buffer vecC(context, CL_MEM_READ_ONLY , (C.size())*sizeof(cl_float));
//Write vectors into buffers
cmdqueue.enqueueWriteBuffer(vecB, 0, 0, (B.size())*sizeof(cl_float), &B[0] );
cmdqueue.enqueueWriteBuffer(vecB, 0, 0, (C.size())*sizeof(cl_float), &C[0] );
//Executing kernel
cl::Kernel kernel(program, "vector_add");
cl::KernelFunctor kernel_func=kernel.bind(cmdqueue, cl::NDRange(GlobalSize), cl::NDRange(workGroupSize));
kernel_func(vecA, vecB, vecC, N);
//Reading back values into vector A
cmdqueue.enqueueReadBuffer(vecA,true,0,N*sizeof(cl_float), &A[0]);
cmdqueue.finish();
//Saving into file.
std::ofstream output("vectorAdd.txt");
for(int i=0;i<N;i++) output<<A[i]<<"\n";
}
catch(cl::Error& err)
{
std::cerr << "OpenCL error: " << err.what() << "(" << err.err() <<
")" << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
The problem is, for smaller values of N, I'm getting the correct result that is 2.6
But for larger values, like the one in the code above (993448) I get garbage output varying between 1 and 2.4.
Here is the Kernel code :
__kernel void vector_add(__global float *A, __global float *B, __global float *C, int N) {
// Get the index of the current element
int i = get_global_id(0);
//Do the operation
if(i<N) A[i] = C[i] + B[i];
}
UPDATE : Ok it seems the code is working now. I have fixed a few minor mistakes in my code above
1) The part where GlobalSize is initialized has been fixed.
2)Stupid mistake in enqueueWriteBuffer (wrong parameters given)
It is now outputting the correct result for large values of N.
Try to change the data type from float to double etc.

How to overload operator>> for bool

I want to parse scalar as bool.
This example works:
#include <yaml.h>
#include <iostream>
#include <sstream>
#include <string>
void operator>> (const YAML::Node & node, bool & b)
{
std::string tmp;
node >> tmp;
std::cout << tmp << std::endl;
b = (tmp == "1") || (tmp == "yes");
}
int main()
{
bool b1, b2;
std::stringstream ss("key: да\notherkey: no");
YAML::Parser parser(ss);
YAML::Node doc;
parser.GetNextDocument(doc);
doc["key"] >> b1;
doc["otherkey"] >> b2;
std::cout << b1 << std::endl;
std::cout << b2 << std::endl;
return 0;
}
But in more complicated case template operator is used:
YAML::operator>><bool> (node=..., value=#0x63f6e8) at /usr/include/yaml-cpp/nodeimpl.h:24
And I get 'YAML::InvalidScalar' if string in not 'yes' or 'no'.
yaml-cpp already reads bools by default, as specified by the YAML spec.
y, yes, true, on
produce true, and
n, no, false, off
produce false. If you want to extend or change this behavior (for example, so that "да" also produces true), as you found out, overloading operator >> in the YAML namespace works.
The reason it needs to be in the YAML namespace (but only for "more complicated examples" - meaning where you don't directly call operator >> with a bool argument) is the way C++ lookup works.
See this answer to my old question for a great explanation.