Consider this use case scenario: I wish to auto complete and provide the skeleton for code constructs like for loop and if else statements. How can I go about doing it?
the user writes this line in VBScript,
function add(a,b) and then presses enter, the program should automatically add the line end function after it.
Also I need to handle the case where there are nested statements like in the case of if and endif statements.
Any help would be greatly appreciated.
thanks
In short: Read the line after the pressing of Enter, grab the keywords with some regular expressions, look up the keywords in a dictionary and perform the coupled function (by use of function pointers) that is added as item to that key.
Now you can create a dictionary with keywords as keys and names of functions (as string) to perform with each keyword.
In a separate module, create a collection of functions that are coupled to certain keywords, like generating the text VbNewLine & "End Function".
To keep everything neat, you should place the regular expressions, keywords and functions to perform with that keywords in separate objects like dictionaries or custom created classes. Don't start with Select Case if you want to go for extensibility.
Related
I'd like to customize auto-completion in bash (such as is described at https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Programmable-Completion) such that a parameter can use auto-completion, where the parameter is an expression that should conform to a defined grammar (LALR, PEG or other).
Assuming the grammar definition already exists, is there any way to automate the generation of the resources needed to add this autocomplete capability to bash?
As an example, let's say I have sql.l and sql.y which I can compile with flex and bison to generate a check_sql executable that takes a single SQL "select" query as a parameter, and then prints "Valid" or "Invalid" depending on whether the query is valid SQL syntax. Further assume the command syntax is:
check_sql <sql query>
Then, if I typed in:
check_sql "sel
and then hit Tab, I would like autocomplete to propose to add "ect" to finish the word "select".
Similarly, if I typed in:
check_sql "select my_column from my_table
and then hit Tab, I would like autocomplete to show options such as "where", "inner", or "having".
Finally, I would like to generate the scripts and resources that implement this behavior, using sql.l, sql.y or both as inputs, so that if/as my grammar definition files change, it is easy to also update the bash completion resources.
Is this possible and/or feasible? I have used this approach to implement autocomplete using Monaco (with a PEG grammar rather than an LALR one)-- and it seems in theory that it shouldn't be too hard to do with bash autocomplete, but I'm not finding any relevant documentation or examples.
What is the most idiomatic way to get some form of context to the yacc parser in goyacc, i.e. emulate the %param command in traditional yacc?
I need to parse to my .Parse function some context (in this case including for instance where to build its parse tree).
The goyacc .Parse function is declared
func ($$rcvr *$$ParserImpl) Parse($$lex $$Lexer) int {
Things I've thought of:
$$ParserImpl cannot be changed by the .y file, so the obvious solution (to add fields to it) is right out, which is a pity.
As $$Lexer is an interface, I could stuff the parser context into the Lexer implementation, then force type convert $$lex to that implementation (assuming my parser always used the same lexer), but this seems pretty disgusting (for which read non-idiomatic). Moreover there is (seemingly) no way to put a user-generated line at the top of the Parse function like c := yylex.(*lexer).c, so in the many tens of places I want to refer to this variable, I have to use the rather ugly form yylex.(*lexer).c rather than just c.
Normally I'd use %param in normal yacc / C (well, bison anyway), but that doesn't exist in goyacc.
I'd like to avoid postprocessing my generated .go file with sed or perl for what are hopefully obvious reasons.
I want to be able to (go)yacc parse more than one file at once, so a global variable is not possible (and global variables are hardly idiomatic).
What's the most idiomatic solution here? I keep thinking I must be missing something simple.
My own solution is to modify goyacc (see this PR) which adds a %param directive allowing one or more fields to be added to the $$ParserImpl structure (accessible as $$rcvr in code). This seems the most idiomatic route. This permits not only passing context in, but the ability for the user to add additional func()s using $$ParserImpl as a receiver.
I'm using MongoDB, so my clusters of data are in dictionaries. Some of these contain references to other Mongo objects. For example, say I have a Person document which has a separate Employer document. I would like to control element access so I can automatically dereference documents. I also have some data with dates, and since PyMongo can't store timezone info, I'd like to store a string timezone alongside the UTC time and have an accessor to the converted times easily.
Which of these options seems the best to you?
Person = {'employer': ObjectID}
Employer = {'name': str}
Option 1: Augmented operations are methods
Examples
print person.get_employer()['name']
person.get_employer()['name'] = 'Foo'
person.set_employer(new_employer)
Pro: Method syntax makes it clear that getting the employer is not just dictionary access
Con: Differences between the syntaxes between referenced objects and not, making it hard to normalize the schema if necessary. Augmenting an element would require changing the callers
Option 2: Everything is an attribute
Examples
print person.employer.name
person.employer.name = 'Foo'
person.employer = new_employer
Pro: Uniform syntax for augmented and non-augmented
?: Makes it unclear that this is backed by a dictionary, but provides a layer of abstraction?
Con: Requires morphing a dictionary to an object, not pythonic?
Option 3: Everything is a dictionary item
Examples
print person['employer']['name']
person['employer']['name'] = 'Foo'
person['employer'] = new_employer
Pro: Uniform syntax for augmented and non-augmented
?: Makes it unclear that some of these accesses are actually method calls, but provides a layer of abstraction?
Con: Dictionary item syntax is error-prone to type IMHO.
Your first 2 options would require making a "Person" class and an "Employer" class, and using __dict__ to read values and setattr for writing values. This approach will be slower, but will be more flexible (you can add new methods, validation, etc.)
The simplest way would be to use only dictionaries (option 3). It wouldn't require any need for oop. Personally, I also find it to be the most readable of the 3.
So, if I were you, I would use option 3. It is nice and simple, and easy to expand on later if you change your mind. If I had to choose between the first two, I would choose the second (I don't like overusing getters and setters).
P.S. I'd keep away from person.get_employer()['name'] = 'Foo', regardless of what you do.
Do not be afraid to write a custom class when that will make the subsequent code easier to write/read/debug/etc.
Option 1 is good when you're calling something that's slow/intensive/whatever -- and you'll want to save the results so can use option 2 for subsequent access..
Option 2 is your best bet -- less typing, easier to read, create your classes once then instantiate and away you go (no need to morph your dictionary).
Option 3 doesn't really buy you anything over option 2 (besides more typing, plus allowing typos to pass instead of erroring out)
I can use all_arguments and all_procedures to list the procedures and functions inside any given package and with DBMS_METADATA I can extract the DDL for that package. Is there an easy way (other than lots of instring and substring calls) to obtain the procedure or function source code separately for each separate block of code in a package.
Something like this:
Owner | Package Name | Object Name | Overload | Arguments | Source
Obviously using substring and instring will present issues with overloaded functions.
All_arguments has the subprogram_id field which according to the very sparse documentation on it looks like it does uniquely reference which procedure it related to in the package but there doesn't appear to be anything that uses it.
Cheers in advance
IIRC, PLSQL allows nested packages and functions. In this case, you'll find that "instring" and "substring" may not be adequate to extract the source code, as you're facing recursion, and string functions typically only handle a smaller class of computations (typically regular expressions). This is a classic problem people have trying to parse languages with simple string manipulation. You can get around limits of string functions by essentially hacking to produce a poor man's parser but this can be a surprising amount of work if you want it to be deadly right, because you have to handle at least the recursive grammar rules that matter for your extraction.
Another way to get reliable access to the elements of a PLSQL package is to use a language parser. The DMS Software Reengineering Toolkit has a full PLSQL parser.
You'd have to extract the package text to a file first, and then apply the PLSQL parser to it; that produces an abstract syntax tree (AST) internally in the parser. Given the name of a function, it is rather easy to search the AST for the function with a matching name. You'd end up with more than one hit if you have overloaded functions; you might qualify the function by the hierarchy in which it is embedded or the information about the arguments that you might have. Having identified a specific function in the AST, one can ask DMS to pretty-print that tree, and it will regenerate the text of (complete with comments) for that function.
I am working in a group that is writing some APIs for tools that we are using in Ruby. When writing API methods, many of my team mates use hash tables as the method's only parameter while I write my methods with each value specified.
For example, a class Apple defined as:
class Apple
#commonName
#volume
#color
end
I would instantiate the class with method:
Apple.new( commonName, volume, color )
My team mates would write it so the method looked like:
Apple.new( {"commonName"=>commonName, "volume"=>volume, "color"=>color )
I don't like using a hash table as the input. To me is seems unnecessarily bulky and doesn't add any clarity to the code. While it doesn't appear to be a big deal in this example, some of our methods have greater than 10 parameters and there will often be hash tables nested in inside other hash tables. I also noticed that using hash tables in this way is extremely uncommon in public APIs(net/telnet is the only exception that I can think of right now).
Question: What arguments could I make to my team members to not use hash tables as input parameters. The bulkiness of the code isn't a sufficient justification(they are not afraid of writing 200-400 character lines) and excessive memory/processing overhead won't work because it won't become an issue with the way our tools will be used.
Actually if your method takes more than 10 arguments, you should either redesign your class or eat dirt and use hashes. For any method that takes more than 4 arguments, using typical arguments can be counter-intuitive while calling the method, because you got to remember the order correctly.
I think best solution would be to simply redesign such methods and use something like builder or fluent patterns.
First of all, you should chide them for using strings instead of symbols for hash keys.
One issue with using a hash is that you then have to check that all the appropriate keys are in it. This makes it useful for optional parameters, but for mandatory one, why not use the built-in functionality of the language? For example, with their method, what happens if I do this:
Apple.new( {"commonName"=>commonName, "volume"=>volume} )
Whereas, with Apple.new(commonName, volume), you know you'll get an ArgumentError.
Named parameters make for more self-documenting code which is nice. But other than that there's not a lot of difference. The Hash allows for more flexibility, especially if you start doing any method aliasing. Also, the various Hash methods in ActiveSupport make setting defaults and verifying inputs pretty painless. I guess this probably wasn't the answer you were looking for.