Antlr4cs: Same grammar different results vs Java tools - c#

I have followed the instructions here: https://github.com/sharwell/antlr4cs/wiki and here: http://www.antlr.org/wiki/display/ANTLR4/Getting+Started+with+ANTLR+v4
I have morphed my grammar from the opening example but it works with the Java tools (antlr4.bat and grun.bat) but not with my console app as configured by the sharwell wiki.
Java (inside a folder with only the Hello.g4 file):
antlr4 Hello.g4
javac *.java
grun Hello prog -gui
I then type "hello world" then Return then "^Z" then Return
The gui pops up an matches my grammar correctly
C# (only difference is the #parser and #lexer directives are not used in the Java version)
Hello.g4:
grammar MetaMeta;
#parser::members
{
protected const int EOF = Eof;
}
#lexer::members
{
protected const int EOF = Eof;
protected const int HIDDEN = Hidden;
}
prog : stmt NL* EOF;
stmt : hello eos;
hello : HELLO ID;
eos : ';' | NL;
HELLO : 'hello';
ID : [a-z]+;
NL : '\r'? '\n';
WS : [ \t]+ -> skip;
Program.cs:
private static void Main(string[] args)
{
(new Program()).Run();
}
public void Run()
{
var text = "hello world\n";
try
{
Console.WriteLine("START");
RunParser(text);
Console.Write("DONE. Hit RETURN to exit: ");
}
catch (Exception ex)
{
Console.WriteLine("ERROR: " + ex);
Console.Write("Hit RETURN to exit: ");
}
Console.ReadLine();
}
private void RunParser(string text)
{
var input = new AntlrInputStream(text);
var lexer = new MetaMetaLexer(input);
var tokens = new CommonTokenStream(lexer);
var parser = new MetaMetaParser(tokens);
var context = parser.prog();
var visitor = new MyVisitor();
visitor.VisitProg(context);
}
When running the program I get the following:
START
HelloVisitor VisitProg
Visit Symbol=<EOF>
DONE. Hit RETURN to exit:
My visitor is the same as the code example on the cs wiki. Thanks for any help. ;)
Scott

If you would have included your visitor code here, you would have received an answer much faster.
The visitor you are using does not override AbstractParseTreeVisitor<Result>.VisitTerminal(ITerminalNode). Therefore, the default implementation of this method is used each time a terminal node is reached, which simply returns DefaultResult() (which by default is just default(Result)).

The modified visitor code is as follows:
public class MyVisitor : AbstractParseTreeVisitor<object>
{
public override object VisitTerminal(ITerminalNode node)
{
var text = node.Symbol.Text;
if (text == "\n")
text = #"\n";
Console.WriteLine(" Visit Symbol={0}", text);
return base.VisitTerminal(node);
}
}
And the modified calling code is as follows:
private void RunParser(string text)
{
var input = new AntlrInputStream(text);
var lexer = new MetaMetaLexer(input);
var tokens = new CommonTokenStream(lexer);
var parser = new MetaMetaParser(tokens);
var context = parser.prog();
var visitor = new MyVisitor();
visitor.Visit(context); //changed to just Visit
}
I added this for completeness, but awarded the correct answer to Sam above.
Thanks,
Scott

Related

Roslyn scripting entry point?

I am building a REPL interface with Blazor webassembly.
I have build a textarea where you can write code. The code compiles successfully. The problem is that the textarea is empty. Normally, as a C# developer, you would see an entry point (the Main method) by which the program starts.
How do I fix that?
Try dotnet is an good example of what I want to achieve. In my case the textarea is empty, but I can program in there. Not sure what the entry point is in my case.
I am really stuck here since I cannot find much about Roslyn scripting with Blazor.
Please help me out.
My code to compile input:
private ScriptState _scriptState = null;
private StringWriter _sw;
private string _output;
public ChallengeCompiler()
{
_sw = new StringWriter();
Console.SetOut(_sw);
Console.SetError(_sw);
}
public string CompileCode(string input)
{
string[] references =
{
"System",
"System.Collections",
"System.Collections.Generic",
"System.Collections.Concurrent",
"System.Console",
"System.Diagnostics.Debug",
"System.Diagnostics.Process",
"System.Diagnostics.StackTrace",
"System.Globalization",
"System.IO",
"System.Reflection",
"System.Runtime",
"System.Runtime.InteropServices",
"System.Text",
"System.Text.Encoding",
"System.Text.RegularExpressions",
"System.Threading",
"System.Threading.Tasks",
"System.Threading.Tasks.Parallel",
"System.Threading.Thread",
"System.ValueTuple",
};
try
{
if (_scriptState == null)
{
_scriptState = CSharpScript.RunAsync(input, ScriptOptions.Default.WithImports(references)).Result;
}
else
{
_scriptState = _scriptState.ContinueWithAsync(input).Result;
}
if (_scriptState.ReturnValue != null && !string.IsNullOrEmpty(_scriptState.ReturnValue.ToString()))
{
_output = _scriptState.ReturnValue.ToString();
}
else
{
_output = _sw.ToString();
}
}
catch (CompilationErrorException e)
{
_output = "-----------------------------------\n";
_output += string.Join(Environment.NewLine, e.Diagnostics);
}
return _output;
}

Keylogger API and converting to a string

I'm attempting to write a simple keylogger that will check typed words against a blacklist and fire a screenshot when a word is triggered. This is because we have a new PREVENT agenda that we have to use in UK schools to capture any possible extremist views.
I've been looking at the Keylogger API from https://github.com/fabriciorissetto/KeystrokeAPI
I'm using the following code as a test but i'm trying to add the characters to a string so i can then fire a comparison with a word list when the user presses the spacebar. The trouble i'm having is that i cannot convert character into a string. Is it possible do this so i can append it to another string a whilst waiting for a spacebar key?
class Program
{
static void Main(string[] args)
{
using (var api = new KeystrokeAPI())
{
api.CreateKeyboardHook((character) => { Console.Write(character); });
Application.Run();
}
}
}
This is what i have so far, the error i get is on the if statement converting character to a string.
static void Main(string[] args)
{
string line = "";
using (var api = new KeystrokeAPI())
{
api.CreateKeyboardHook((character) => {
line += character.ToString();
if (character.ToString() = "space")
{
Console.Write("Spacebar Hit");
}
Console.Write(character.KeyCode);
});
Application.Run();
}
}
Edit.
I rewrote this.
Captures both spaces and enter commands
static void Main(string[] args)
{
string line = string.Empty;
using (var api = new KeystrokeAPI())
{
api.CreateKeyboardHook((character) => {
if (character.KeyCode.ToString() == "Space" || character.KeyCode.ToString() == "Return")
{
if(BannedWordsCheck(line))
{
Console.WriteLine("Banned Word Typed: " + line);
}
line = string.Empty;
}
else
{
line += character.KeyCode.ToString();
}
});
Application.Run();
}
}
static bool BannedWordsCheck(string word)
{
if(word.ToLower().Contains("terror"))
{
return true;
}
else
{
return false;
}
}
The error you are receiving in your code is due to the following line
if (character.ToString() = "space")
You are attempting to assign the string literal "space" to character.ToString(), I also have this error in my comment which I can't edit anymore.
Here's a snippet that will check the key code against an enum instead of a string, it will then call the HandleComparison method if Space was pressed, and then clear out the StringBuilder
The only issue I found here is that pressing Shift will prefix the string with <shift>, so some additional logic will have to be applied for action keys, but this is a base to get you started with a working code sample.
I hope this helps.
class Program
{
private static StringBuilder builder;
static void Main(string[] args)
{
using (var api = new KeystrokeAPI())
{
builder = new StringBuilder();
api.CreateKeyboardHook(HandleKeyPress);
Application.Run();
}
}
private static void HandleKeyPress(KeyPressed obj)
{
// To be more reliable, lets use the KeyCode enum instead
if (obj.KeyCode == KeyCode.Space)
{
// Spacebar was pressed, let's check the word and flush the StringBuilder
HandleComparison(builder.ToString());
builder.Clear();
return;
}
// Space wasn't pressed, let's add the word to the StringBuilder
builder.Append(obj);
}
// Handle comparison logic here, I.E check word if exists on blacklist
private static void HandleComparison(string compareString)
{
Console.WriteLine(compareString);
}
}
Could you use the StringBuilder as a buffer?
something like this
var buffer = new StringBuilder();
using (var api = new KeystrokeAPI())
{
api.CreateKeyboardHook((character) => {
if (character.ToString() == " ")
{
//check the word
CallSomeMethodToCheckWord(buffer.ToString());
//reset the buffer
buffer = new StringBuilder();
}
else
{
//ToString returns special characters in it, so you could append here and parse later, or parse here.
buffer.Append(character.ToString());
}
});
Application.Run();
}

How to write english transcription in console correctly?

I want to write english transcription in console.
In debugger I have this səˈdʒest
but in console I have s??d?est.
How to resolve this problem ? Thanks!
Up
Client for getting transcription
class TranslationFormattedResult
{
public string Transcription { get; set; }
public List<string> TranslatedWordList = new List<string>();
}
class TranslatorClient
{
private TranslationServiceSoapClient _client = new TranslationServiceSoapClient("TranslationServiceSoap");
public async Task<TranslationFormattedResult> GetTranslationAsync(string word)
{
var result = await _client.GetTranslationAsync("er", "General",
word,
lang: "ru",
limit: 3000,
useAutoDetect: true,
key: "",
ts: "MainSite",
tid: "");
var translationResult = new TranslationFormattedResult {Transcription = await GetTranscriptionAsync(result)};
return translationResult;
}
private async Task<string> GetTranscriptionAsync(TranslationResult result)
{
var task = new Task<string>(() =>
{
string pr = null;
string pattern = "\\[.+\\]";
var match = Regex.Match(result.result, pattern);
if(match.Success)
{
pr = match.Value.Trim('[', ']');
}
return pr;
});
task.Start();
return await task;
}
}
And main method
class Program
{
static void Main(string[] args)
{
//this works
var client = new TranslatorClient();
var ts = client.GetTranslationAsync("suggest")
.ContinueWith(r =>
{
var transcription = r.Result.Transcription;
Console.OutputEncoding = Encoding.Unicode;
Console.WriteLine(transcription);
Console.WriteLine("press any key");
Console.ReadKey();
}
);
ts.Wait();
}
}
You should:
set the OutputEncoding to Unicode: Console.OutputEncoding = Encoding.Unicode;
run your program
right click on the console window
in the properties window change the console font and set it to Consolas.
class Program {
static void Main( string[ ] args ) {
Console.OutputEncoding = Encoding.Unicode;
Console.WriteLine( "səˈdʒest" );
}
}
The result in the console is:
Is this Russian?
If so, try running chcp 866 at the command line.
Refer to this
http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/chcp.mspx?mfr=true
This answer also suggests a specific (or at least, different) font may need to be selected (not sure if this applies to Russian or not) Unicode characters in Windows command line - how?

some delay processing message in MessageInterceptor

Sorry, my english is not quite well.
I'm new in programming world and tried to create an application using messageinterceptor on windows mobile 6.5.3.
but when i send text message to my phone, there was delay about 30 seconds or more before the message is processed, either text message which contain keywords or not.
I read several sources before deciding to try to make my own application, but these source are using Windows Form (GUI), instead of using Windows Form, i make it run in console mode.
here is the code:
using System;
using System.Linq;
using System.Collections.Generic;
using System.Text;
using Microsoft.WindowsMobile.PocketOutlook.MessageInterception;
using Microsoft.WindowsMobile.PocketOutlook;
using Microsoft.WindowsMobile;
using System.IO;
namespace PenerimaPesan
{
class Program
{
static void Main(string[] args)
{
string applicationID;
applicationID = "tracker";
MessageInterceptor pesanmasuk = null;
pesanmasuk = new MessageInterceptor();
pesanmasuk.EnableApplicationLauncher(applicationID);
if (MessageInterceptor.IsApplicationLauncherEnabled(applicationID))
{
string keyword;
StreamReader key = new StreamReader(#"\Windows\conf.txt");
string data = key.ReadToEnd();
string[] isi = data.Split(new char[] { '\n' });
keyword = isi[1];
keyword = keyword.Replace(" ", "");
pesanmasuk = new MessageInterceptor(InterceptionAction.NotifyAndDelete, false);
pesanmasuk.MessageCondition = new MessageCondition(MessageProperty.Body, MessagePropertyComparisonType.StartsWith, ""+keyword);
pesanmasuk.MessageReceived += new MessageInterceptorEventHandler(pesanmasuk_MessageReceived);
}
}
static void pesanmasuk_MessageReceived(object sender, MessageInterceptorEventArgs e)
{
SmsMessage pesan = e.Message as SmsMessage;
if (pesan != null)
{
string perintah;
string[] command = pesan.Body.Split(new char[] { '.' });
perintah = command[1];
if (perintah == "helo")
/*do some Stuff*/
}
}
}
I've never used MessageInterceptor, so I decided I'd try to implement this code in my application. To test it, I renamed Main to Main2, then cleaned it up to match "my style".
Anyway, I ran into errors when I tried wrapping the MessageInterceptor in a using block - not because MessageInterceptor does not implement IDispose, but because you have declared a new instance of it.
Take a look at this snippet of your code:
MessageInterceptor pesanmasuk = new MessageInterceptor();
pesanmasuk.EnableApplicationLauncher(applicationID);
if (MessageInterceptor.IsApplicationLauncherEnabled(applicationID)) {
string keyword;
StreamReader key = new StreamReader(#"\Windows\conf.txt");
string data = key.ReadToEnd();
string[] isi = data.Split(new char[] { '\n' });
keyword = isi[1];
keyword = keyword.Replace(" ", "");
pesanmasuk = new MessageInterceptor(InterceptionAction.NotifyAndDelete, false);
OK, right there. Stop. You created a new instance of your pesanmasuk variable, set Properties, did some checking, worked with data from a text file, then...
Created a new instance of your pesanmasuk variable.
All of your previous settings are now whipped out.
I'm guessing your first instance is running and perhaps the second instance has to wait for the first instance to time out before it can be created.
At this point, I'm interested to learn just how to use this MessageInterceptor on MSDN, looked into the example there, and came up with this [untested] version:
static void Main2(string[] args) {
const string stackOverflowUrl = #"http://stackoverflow.com/questions/8520488/some-delay-processing-message-in-messageinterceptor";
string empty = String.Empty;
StreamReader key = new StreamReader(#"\Windows\conf.txt");
string data = key.ReadToEnd();
string[] lines = data.Split(new char[] { '\n' });
string keyword = lines[1].Replace(" ", empty);
string applicationID = "trackingApplication";
using (MessageInterceptor smsInterceptor = new MessageInterceptor(applicationID, false)) {
smsInterceptor.InterceptionAction = InterceptionAction.NotifyAndDelete;
smsInterceptor.MessageCondition = new MessageCondition(MessageProperty.Body, MessagePropertyComparisonType.StartsWith, empty + keyword);
smsInterceptor.MessageReceived += new MessageInterceptorEventHandler(Intercept_MessageReceived);
smsInterceptor.EnableApplicationLauncher(applicationID);
if (MessageInterceptor.IsApplicationLauncherEnabled(applicationID)) {
// Here, you'd need to launch your Form1 or enable some timer,
// otherwise the code will return immediately and the MessageInterceptor
// instance will be disposed of.
}
smsInterceptor.MessageReceived -= MessageInterceptorEventHandler;
}
}
static void Intercept_MessageReceived(object sender, MessageInterceptorEventArgs e) {
SmsMessage newMessage = e.Message as SmsMessage;
if (newMessage != null) {
Console.WriteLine("From: {0}", newMessage.From.Address);
Console.WriteLine("Body: {0}", newMessage.Body);
string[] command = newMessage.Body.Split(new char[] { '.' });
string line = command[1];
if (line == "helo") {
/*do some Stuff*/
}
}
}
I hope this helps, but keep in mind that I've never actually used this control and my code has not been tested.

Running IronPython object from C# with dynamic keyword

I have the following IronPython code.
class Hello:
def __init__(self):
pass
def add(self, x, y):
return (x+y)
I could make the following C# code to use the IronPython code.
static void Main()
{
string source = GetSourceCode("ipyth.py");
Engine engine = new Engine(source);
ObjectOperations ops = engine._engine.Operations;
bool result = engine.Execute();
if (!result)
{
Console.WriteLine("Executing Python code failed!");
}
else
{
object klass = engine._scope.GetVariable("Hello");
object instance = ops.Invoke(klass);
object method = ops.GetMember(instance, "add");
int res = (int) ops.Invoke(method, 10, 20);
Console.WriteLine(res);
}
Console.WriteLine("Press any key to exit.");
Console.ReadLine();
}
Can I make this code simpler with dynamic DLR?
The IronPython In Action book has the simple explanation about it at <15.4.4 The future of interacting with dynamic objects>, but I couldn't find some examples.
ADDED
I attach the source/batch file for the program.
Program.cs
runme.bat
Yes, dynamic can make your code simplier
var source =
#"
class Hello:
def __init__(self):
pass
def add(self, x, y):
return (x+y)
";
var engine = Python.CreateEngine();
var scope = engine.CreateScope();
var ops = engine.Operations;
engine.Execute(source, scope);
var pythonType = scope.GetVariable("Hello");
dynamic instance = ops.CreateInstance(pythonType);
var value = instance.add(10, 20);
Console.WriteLine(value);
Console.WriteLine("Press any key to exit.");
Console.ReadLine();

Categories