I'm going through the ParseKit example and trying to modify it to suit my needs and running into this problem. As soon as I pass in the grammar file to parserFromGrammar:assembler, I get an error:
[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array
I thought maybe it was because my grammar files had token names with underscores in them. Does ParseKit support underscores? What would the method name be that gets called back? Aka would the token name "foo_bar" call a method didMatchFoo_bar?
I then took out all the underscored names and it still gives me that error. I'm using the example grammar file from the ParseKit website:
#start = sentence+;
sentence = adjectives 'beer' '.';
adjectives = cold adjective*;
adjective = cold | freezing;
cold = 'cold';
freezing = 'freezing';
Thanks
Developer of ParseKit here. 2 things:
To answer your first question, I believe the answer is YES.
I just tried out the grammar and it seems to work for me. However, I am using the latest version of ParseKit from Google Code (not GitHub. GitHub is out of date. sorry.)
So checkout ParseKit from Google Code here:
https://parsekit.googlecode.com/svn/trunk
And then select the "DebugApp" target and "DebugApp" Executable and run.
In the Xcode project, do a global search for "cold freezing beer". you'll see I've added your example as the default example run in DebugApp. Seems to work ok.
Related
I'm removing builder pattern on multiple places. Following example would help me with the task, but mainly I'd like to learn how to use live templates more.
Preexisting code:
Something s = s.builder
.a(...)
.b(bbb)
.build();
and I'd like to remove it to:
Something s = new Something();
s.setA(...);
s.setB(bbb);
part of it can be trivially done using intellij regex, pattern: \.(.*)$ and replacement .set\u$1. Well it could be improved, but lets keep it simple.
I can create surround live template using variable:
regularExpression(SELECTION, "\\.(.*)", "\\u$1")
but \\u will be evaluated as u.
question 1: is it possible to get into here somehow \u functionality?
but I might get around is differently, so why not try to use live temlate variable:
regularExpression(SELECTION, "\\.(.)(.*)", concat(capitalize($1), "$2"))
but this does not seem to work either. .abc is replaced to bc
question 2: why? How would correct template look like? And probably, if it worked, this would behave incorrectly for multiline input. How to make it working and also for multiline inputs?
sorry for questions, I didn't find any harder examples of live templates than trivial replacements.
No, there is no \u functionality in the regularExpression() Live Template macro. It is just a way to call String.replaceAll(), which doesn't support \u.
You can create a Live Template like this:
set$VAR$
And set the following expression for the $VAR$ variable:
capitalize(regularExpression(SELECTION, "\\.(.*)", "$1"))
I've a fairly simple question about ParseKit and parsing timestamps... how do I go about forcing the symbolic-nature of a dot/period.
For example, if I am trying to parse 2008-01-25, I could use something like date = /\d{4}/ '-' /\d{2}/ '-' /\d{2}/. In fact, there is a date.grammar shipped with ParseKit that does exactly this (interestingly enough, though, the provided grammar doesn't work in the DemoApp unless you add #symbolState='-';, but I digress...)
However, what do I do if I want to parse a date with dots in it... for example, 2008.01.25 or 2008-01-25-12.34.45. I've tried added '.' to the #symbolState directive but it just keeps getting ignored. Note that I am relying on the DemoApp to test my grammars at the moment... not sure if that makes any difference.
Any thoughts would be much appreciated.
Developer of ParseKit here.
First, thanks for the heads up on the bug in the date.grammar file. I have fixed it.
As for your main question, I'm pretty sure what you are trying was not possible with ParseKit until now.
That is, ParseKit's tokenizer (PKTokenizer) was not able to produce only whole number Number tokens. Numbers were always tokenized as floating point which means it was impossible to parse input like 3.14 as three separate tokens 3 (Number) . (Symbol) 14 (Number). Rather it would always be tokenized as 3.14.
Good news: I've added this capability with a new method:
-[PKNumberState allowsFloatingPoint]
which defaults to YES.
And I added a matching Tokenizer Directive which you can use in your ParseKit Grammars like:
#allowsFloatingPoint = NO;
NOTE you'll need to checkout the latest HEAD of trunk on Google Code to see this feature.
So, here's an example date grammar which does roughly what you were asking for with the new feature:
#symbolState = '.';
#allowsFloatingPoint = NO;
#start = date;
date = year dot month dot day;
year = /\d{4}/;
month = /\d{2}/;
day = /\d{2}/;
dot = '.';
I'm wondering if a simpler idea might be to get parseKit to simply parse the date as a string, and then hand it off to the NSDate::dateWithNaturalLanguageString:locale: orNSDate::dateWithNaturalLanguageString: for processing.
From Parsekit: how to match individual quote characters?
If you define a parser:
#start = int;
int = /[+-]?[0-9]+/
Unfortunately it isn't going to be parsing any integers prefixed with a "+", unless you include:
#numberState = "+" // at the top.
In the number parse above, the "Symbol" default parser wasn't even mentioned, yet it is still active and overrides user defined parsers.
Okay so with numbers you can still fix it by adding the directive. What if you're trying to create a parser for "++"? I haven't found any directive that can make the following parser work.
#start = plusplus;
plusplus = "++";
The effects of default parsers on the user parser seems so arbitrary. Why can't I parse "++"?
Is it possible to just turn off default Parsers altogether? They seem to get in the way if I'm not doing something common.
Or maybe I've got it all wrong.
EDIT:
I've found a parser that would parse plus plus:
#start = plusplus;
plusplus = plus plus;
plus = "+";
I am guessing the answer is: the literal symbols defined in your parser cannot overlap between default parsers; It must be contained completely by at least once of them.
Developer of ParseKit here.
I have a few responses.
I think you'll find the ParseKit API highly elegant and sensible, the more you learn. Keep in mind that I'm not tooting my own horn by saying that. Although I built ParseKit, I did not design the ParseKit API. Rather, the design of ParseKit is based almost entirely on the designs found in Steven Metsker's Building Parsers In Java. I highly recommend you checkout the book if you want to deeply understand ParseKit. Plus it's a fantastic book about parsing in general.
You're confusing Tokenizer States with Parsers. They are two distinct things, but the details are more complex than I can answer here. Again, I recommend Metsker's book.
In the course of answering your question, I did find a small bug in ParseKit. Thanks! However, it was not affecting your outcome described above as you were not using the correct grammar to get the outcome it seems you were looking for. You'll need to update your source code from The Google Code Project now, or else my advice below will not work for you.
Now to answer your question.
I think you are looking for a grammar which both recognizes ++ as a single multi-char Symbol token and also recognizes numbers with leading + chars as explicitly-positive numbers rather than a + Symbol token followed by a Number token.
The correct grammar I believe you are looking for is something like this:
#symbols = '++'; // declare ++ as a multi-char symbol
#numberState = '+'; // allow explicitly-positive numbers
#start = (Number|Symbol)*;
Input like this:
++ +1 -2 + 3 ++
Will be tokenized like so:
[++, +1, -2, +, 3, ++]++/+1/-2/+/3/++^
Two reminders:
Again, you will need to update your source code now to see this work correctly. I had to fix a bug in this case.
This stuff is tricky, and I recommend reading Metsker's book to fully understand how ParseKit works.
I'm using Parsekit for XCode but this problem may well apply to most parser generators. I parse a script with a gammer and it works fine. However I'm running into problems with the next step. Consider the grmmer:
#start = line+;
line = tree;
tree = 'tree' fruits branches;
fruits = 'with' 'fruits' Number;
branches = 'with' 'branches' Number;
And the script to pass:
tree with fruits 8 with branches 12
If I then implemenet methods to match, fruits and branches will be matched once, this is expected.
However tree will be matched twice, why? This stops me from building the parse tree I want.
Thanks for any help!
Developer of ParseKit here. I think you might actually be asking the same question as this:
parsekit given unexpected calls to selectors
If you read through the comments I made on that question, I think you will find the answer. Let me know if not.
The documentation in the appscript objc-trunk randomly uses ruby in the section called "Performance Issues".
require "appscript"
include Appscript
desiredEmail = 'sam.brown#foo.com'
p app('Address Book').people[
its.emails.value.contains(desiredEmail)
].name.get
How would this be written in Objective-C? I apologize if this seems like an overly basic question, I have 0 experience with Ruby.
Thanks.
If you run the ruby script and use ASTranslate it should translate the raw appscript commands to Objc-appscript.
Edit01:
I think it will look something like this. I haven't run the tool to make the glue code so I'm guessing about the way the app name shows up.
#import "AddressBookGlue.h" //Dont know the precise name
AddressBookApplication *abApp=[[AddressBookApplication alloc] initWithName: #"Address Book.app"];
NSString *desiredEmail=#"sam.brown#foo.com"
NSString *returnedName= [[[[[[abApp people] emails] value] contains:desiredEmail] name] get];
Basically, it follows the same rules that Objectic-c uses when converting from a dot syntax: anywhere there is a dot in the original syntax, expect a bracket in Objective-C.
I might add that if you're going to be doing a lot of this type scripting, it would be best to spend a day or two learning the basics of ruby or python. It's a lot easier to work with OSA in a dot syntax than a nested syntax. Just looking at all those brackets in the documentation for Objc-appscript makes my eyes water.
Apologies for the incompleteness of the objc-appscript manual, which was originally ported from rb-appscript as you can tell. (FWIW, I should have some time to work on appscript this spring.)
Translating the Ruby code back to AppleScript first is probably the easiest approach:
tell application "Address Book"
get name of every person where value of its email contains "hengist.podd#virgin.net"
end tell
Running it through ASTranslate gives this:
#import "ABGlue/ABGlue.h"
ABApplication *addressBook = [ABApplication applicationWithName: #"Address Book"];
ABReference *ref = [[[addressBook people] byTest: [[[ABIts emails] value] contains: #"hengist.podd#virgin.net"]] name];
id result = [ref getItem];
From what I understand, that's printing the name of every person who has an email of "sam.brown#foo.com".
There's no direct correlation for how to do this in Cocoa. Fortunately for you, Address Book is scriptable, which means you can use the Scripting Bridge framework to interact with it from a Cocoa app.
This page has a really great explanation on how to simply interact with Mail.app via ScriptingBridge: http://robnapier.net/blog/scripting-bridge-265
Hopefully that should give you enough information to get going in the right direction.