I'm trying to write a grammar for Parsekit to be used in my iphone app. Am I doing this correctly?
#start = wff;
wff = disjunction ('IMPLIES' | disjunction);
disjunction = conjunction ('OR' | conjunction)*;
conjunction = notexpression ('AND' | notexpression)*'
notexpression = ('NOT')+ primaryexpression;
primaryexpression = (literal | '(' wff ')');
literal = (A | B | C | D | E | F | G | H | I | J | K | L | M | N |O | P | Q | R | S | T | U | V | W | X | Y | Z);
I am getting the error:
2012-11-26 10:41:06.348 SemanticTab[4092:c07] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Could not build ClassName from token array for parserName: conjunction'
*** First throw call stack:
When trying to parse P OR Q?
Developer of ParseKit here.
I see two obvious problems:
The line with the conjunction production definition is terminated with a ' (single quote). That should instead be a ; (semi colon).
The definition for the literal production is not valid. There are no productions called A, B, C, etc. defined. However, if I understand your intention, the easier way to define literal is to use the built-in Word production:
literal = Word;
Related
I've work to do on legacy system using PostgreSQL v9.2.8 I try to run a query:
SELECT ARRAY['a', 'b']::text[] && ARRAY['a', 'c', 'd']::text[];
which end up with an error:
ERROR: operator is not unique: text[] && text[]
LINE 1: select array['a', 'b']::text[] && array['a', 'c', 'd']::text...
^
HINT: Could not choose a best candidate operator. You might need to add explicit type casts.
Differently from many question asked here about similar issue, types are specified and I can't be more explicit here.
I need to mention that extensions: btree_gin, btree_gist and intarray are installed, but I can't spot any duplicated operator for text arrays.
Running:
SELECT oprname, oprcode,
l_arg.typname l_arg_type, l_arg.typcategory l_arg_cat,
r_arg.typname r_arg_type, r_arg.typcategory r_arg_cat
FROM pg_operator o
JOIN pg_namespace n ON n.oid = o.oprnamespace
join pg_type l_arg on l_arg.oid = o.oprleft
join pg_type r_arg on r_arg.oid = o.oprright
WHERE oprname ilike '%&&%'
shows:
| oprname | oprcode | l_arg_type | l_arg_cat | r_arg_type | r_arg_cat |
|---------|----------------|------------|-----------|------------|-----------|
| && | poly_overlap | polygon | G | polygon | G |
| && | box_overlap | box | G | box | G |
| && | tintervalov | tinterval | T | tinterval | T |
| && | circle_overlap | circle | G | circle | G |
| && | arrayoverlap | anyarray | P | anyarray | P |
| && | tsquery_and | tsquery | U | tsquery | U |
| && | range_overlaps | anyrange | P | anyrange | P |
| && | _int_overlap | _int4 | A | _int4 | A |
------------------------------------------------------------------------------
And listing operators families:
SELECT am.amname AS index_method,
opf.opfname AS opfamily_name,
amop.amopopr::regoperator::text AS opfamily_operator
FROM pg_am am, pg_opfamily opf, pg_amop amop
WHERE opf.opfmethod = am.oid AND
amop.amopfamily = opf.oid
and amop.amopopr::regoperator::text ilike '%&&%'::text
ORDER BY index_method, opfamily_name, opfamily_operator;
shows
-------------------------------------------------------------
| index_method | opfamily_name | opfamily_operator |
|--------------|------------------|-------------------------|
| gin | array_ops | &&(anyarray,anyarray) |
| gin | gin__int_ops | &&(integer[],integer[]) |
| gist | box_ops | &&(box,box) |
| gist | circle_ops | &&(circle,circle) |
| gist | gist__int_ops | &&(integer[],integer[]) |
| gist | gist__intbig_ops | &&(integer[],integer[]) |
| gist | poly_ops | &&(polygon,polygon) |
| gist | range_ops | &&(anyrange,anyrange) |
-------------------------------------------------------------
Has the issue something to do with some bizarre conflict between &&(anyarray,anyarray) and two &&(integer[],integer[]) operators?
What I ultimately trying to achieve is creating a two column gin index
CREATE INDEX concurrently public_some_table_index
ON public.some_table
USING gin
( (array[text_col_01, text_col_02]) COLLATE pg_catalog."default" _text_ops );
supposedly used in queries like
SELECT * FROM public.some_table foo
WHERE
(array[foo.text_col_01, foo.text_col_02]) && array['abc', 'def', 'ghi', 'jkl']::text[]
Index creation ends up fine. Just using && in query fails as described above.
Update:
I've checkd on clean installation of Postgresql 9.2.8 after restoration of schema dump (pg_dump -s) as jjanes suggested. The problem still occurs.
When I tried to restore schema only dump to fresh installation, error persists. It is possible that this particular cluster which I'm working on has some problem. But I can really tell what it is.
Also since PostgreSQL 9.2 is not supported it's hard to expect abundant feedback to my question.
I'd like to share what I've done to overcome this obstacle of mine.
In the end I've created new function in public schema
CREATE OR REPLACE FUNCTION textarray_overlap(text[], text[])
RETURNS boolean AS
$BODY$
SELECT pg_catalog.arrayoverlap($1, $2);
$BODY$
LANGUAGE sql STABLE SECURITY DEFINER
COST 100;
ALTER FUNCTION textarray_overlap(text[], text[])
OWNER TO postgres;
GRANT EXECUTE ON FUNCTION textarray_overlap(text[], text[]) TO postgres;
GRANT EXECUTE ON FUNCTION textarray_overlap(text[], text[]) TO public;
The function takes text arrays as arguments and just calls bult-in pg_catalog.arrayoverlap(annyaray, anyarray).
Having that I've created new && operator for text arrays which uses this function.
CREATE OPERATOR &&(
PROCEDURE = textarray_overlap,
LEFTARG = text[],
RIGHTARG = text[],
COMMUTATOR = &&,
RESTRICT = contsel,
JOIN = contjoinsel);
COMMENT ON OPERATOR &&(text[], text[]) IS 'overlap';
That solves my problem, because I suppose now server has dedicated operator for checking if text arrays overlap.
SELECT ARRAY['a', 'b']::text[] && ARRAY['a', 'c', 'd']::text[];
Returns TRUE.
So I searched a bit and found that you can do a product of rows in Oracle using a GROUP BY and a nifty mathematical formula: exp(sum(ln(some_col))). It's pretty awesome, but unfortunately doesn't work when some_col is potentially zero (because ln(0) is not possible as ln(x) is negative infinity as it approaches zero).
Example query:
select
a, b, c
sum(d) d,
sum(e) e,
exp(sum(ln(f))) f
from x
group by a, b, c;
Obviously since this is a product of values, if one of them is zero, the product would be zero. The immediate thought would be to use a case, but that would require the case statement to be on an aggregate value or something in the GROUP BY... which it isn't. I can't just exclude those rows because I still need sum(d) and sum(e).
Any thoughts on a good way to do this while dealing with potential zeroes? I was thinking about something involving over(partition by ...), but in reality, my query groups by 12 columns and there are 20 other columns being aggregated. That query could get reeaaaal ugly, but if it's the only solution, I suppose I don't have a choice.
Side question: is there any particular reason there isn't a product function in Oracle? Seems like it'd be such a basic thing to include like sum is.
Note: This is Oracle 12c.
Example:
If I had an input table like this (matching with the query above):
| a | b | c | d | e | f |
+-----+-----+-----+---+---+---+
| foo | bar | hoo | 1 | 2 | 2 |
| foo | bar | hoo | 3 | 4 | 3 |
| foo | bar | hoo | 2 | 5 | 0 |
| foo | bar | mee | 1 | 2 | 2 |
| foo | bar | mee | 3 | 4 | 3 |
I would expect output like this:
| a | b | c | d | e | f |
+-----+-----+-----+---+----+---+
| foo | bar | hoo | 6 | 11 | 0 |
| foo | bar | mee | 4 | 6 | 6 |
However, because the third row has a 0 for f, we naturally get ORA-01428: argument '0' is out of range for ln(0).
First, log(0) is not undefined - it's negative infinity.
Second: in Oracle you can generate a negative infinity, but you'll have to use BINARY_FLOAT.
select a, b, c,
sum(d) d,
sum(e) e,
exp(sum(CASE WHEN f <> 0 THEN ln(f) ELSE -1/0F END)) f
from x
group by a, b, c;
Using your data this generates:
A B C D E F
foo bar hoo 6 11 0
foo bar mee 4 6 6.0000001304324524E+000
Note that introducing logarithms and power functions will introduce some rounding issues, but this should at least get you started.
dbfiddle here
TO NEGATIVE INFINITY...AND BEYOND!!!!!!
:-)
I am using the following grammar:
#JSGF V1.0;
grammar tag;
public <tag> = <tagPart> +;
<tagPart> = <digit> | <letter>;
<digit> = oh | zero | one | two | three | four | five | six |seven | eight | nine ;
<letter> = a | b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v | w | x | y | z ;
Everything works well unless I add weights. Running with weights:
<tagPart> = /0.8/ <digit> | /0.1/ <letter>;
I am getting the following error:
Exception in thread "main" java.lang.NullPointerException
at edu.cmu.sphinx.jsgf.JSGFGrammar.getNormalizedWeights(JSGFGrammar.java:49)
The way I am using grammar is:
Configuration configuration = new Configuration();
configuration.setAcousticModelPath("file:/E/sphinx4-5prealpha-src/sphinx4-data/src/main/resources/edu/cmu/sphinx/models/en-us/en-us");
configuration.setDictionaryPath("file:/E/sphinx4-5prealpha-src/sphinx4-data/src/main/resources/edu/cmu/sphinx/models/en-us/cmudict-en-us.dict");
configuration.setGrammarPath("file:/E/sT/src/main/resources/");
configuration.setGrammarName("tag");
configuration.setUseGrammar(true);
StreamSpeechRecognizer recognizer = new StreamSpeechRecognizer(configuration);
I'm sorry for delay, this issue has been just fixed in trunk in revision 13217, please update and try again, it should work.
I downloaded the TL Grammar from https://raw.githubusercontent.com/bkiers/tiny-language-antlr4/master/src/main/antlr4/tl/antlr4/TL.g4
And after attempting to try it, I realized the grammar is unable to handle user defined function calls at the top-level
For example, if your file contents are:
def s(n)
return n+n;
end
s("5", "6");
And you listen for a FunctionCallExpression, you don't get a callback. However, if your file contents are:
def s(n)
return n+n;
end
s(s("5"))
you do get the call back.
Your input:
s("5", "6");
is matched by the statement (not an expression!):
functionCall
: Identifier '(' exprList? ')' #identifierFunctionCall
| ...
;
and "5", "6" are two expressions matched by exprList.
The first s in your input s(s("5")) will again match identifierFunctionCall, and the inner s will be matched as an expression (a functionCallExpression to be precise).
Here are the different parse trees:
s("5", "6");
'- parse
|- block
| '- statement
| |- identifierFunctionCall
| | |- s
| | |- (
| | |- exprList
| | | |- stringExpression
| | | | '- "5"
| | | |- ,
| | | '- stringExpression
| | | '- "6"
| | '- )
| '- ;
'- <EOF>
s(s("5"));
'- parse
|- block
| '- statement
| |- identifierFunctionCall
| | |- s
| | |- (
| | |- exprList
| | | '- functionCallExpression
| | | '- identifierFunctionCall
| | | |- s
| | | |- (
| | | |- exprList
| | | | '- stringExpression
| | | | '- "5"
| | | '- )
| | '- )
| '- ;
'- <EOF>
In short: the grammar works as it is supposed to.
EDIT
A valid TL script is a code block where each code block consists of statements. To simplify the grammar and eliminate some ambiguous rules (which was needed for the older ANTLRv3), it was easiest to not allow a statement to be a simple expression. For example, the following code is not a valid TL script:
1 + 2;
I.e. 1 + 2 is not a statement, but an expression.
However a function call might be a statement, but, when placed at the right hand side of an assignment statement, it could also be an expression:
foo(); // this is a statement
i = foo(); // now foo is an expression
That is why you observed one s(...) to trigger a certain enter...() method, while the other did not.
I have the following DAG
A --> B
| |
v v
C --> D
Here is the closure table
| Ancestor | Descendant | Depth |
---------------------------------
| A | A | 0 |
| A | B | 1 |
| A | C | 1 |
| A | D | 2 |
| A | D | 2 |
| B | B | 0 |
| B | D | 1 |
| C | C | 0 |
| C | D | 1 |
| D | D | 0 |
How would I go about removing path B > D (thus removing A > B > D) without also removing A > C > D and C > D.
Right now I'm using the following query but it only works when every node only has 1 parent.
DELETE FROM `Closure`
WHERE `Descendant` IN (SELECT `Descendant` FROM `Closure` WHERE `Ancestor`=#Node)
AND `Ancestor` NOT IN (SELECT `Descendant` FROM `Closure` WHERE `Ancestor`=#Node);
Given your current model I'm not sure it's possible. I'd propose that you add a column to count the number of paths tracking how many different ways there are to get from any node X to node Y.
So rather than your table you end up with
| Ancestor | Descendant | Depth | Refs |
-----------------------------------------
| A | A | 0 | 1 |
| A | B | 1 | 1 |
| A | C | 1 | 1 |
| A | D | 2 | 2 |
| B | B | 0 | 1 |
| B | D | 1 | 1 |
| C | C | 0 | 1 |
| C | D | 1 | 1 |
| D | D | 0 | 1 |
Removing a node would then entail an update statement followed by a delete statement.
The update would, instead of deleting the entries it finds, decrement the number of references for that entry. Then you could delete the entries with 0 or fewer references afterwards.
Coming up with a SQL query which does the update is escaping me at the moment but in theory this should work without having to completely reconstruct the closure table...
First, I believe there is a duplicate entry in your table. (A,D) appears twice. Second, after removing the edge (B,D), the following paths should remain:
Node self-maps: (A,A), (B,B), (C,C), (D,D)
(A,B)
(A,C)
(A,D) ( through C )
Thus, to remove the edge (B,D) in this example, all that is required is to remove that one row:
Delete MyTable
Where Ancestor = 'B'
And Descendant = 'D'
A closure table is still only mapping relations between two nodes. What makes it special is that it is mapping every indirect relation effectively as a direct relation. The edge (B,D) is simply saying that you can get from B to D. That row alone says nothing about how you got to B nor does it say anything about how many nodes it took to get from B to D; it simply saying you can get from B to D. Thus, there is no edge listed for A > B > D per se. Rather, all that is captured is that you can get from A to B and from A to D which is still true even if the edge (B,D) is removed.
In natural language, that would be: "Delete ancestor-descendant relashionship to D, if there is no parent of D besides B that is also a descendant of A". Is that correct?
(Edit: no, that's not correct; not only relashionships to D must be removed, but also relashionships to every descendant of D. Thus, that criteria is not valid...)
My tentative SQL would then be:
DELETE a
FROM Closure AS a
INNER JOIN Closure AS b ON a.Descendant = b.Descendant
WHERE
a.Descendant IN (SELECT Descendant FROM Closure WHERE Ancestor = {Child}) AND
b.Depth = 1 AND
b.Ancestor != {Parent} AND
a.Ancestor NOT IN (SELECT Ancestor FROM Closure WHERE Descendant = b.Ancestor)
(Sorry if I got the query wrong - or used non-standard features - I'm not actually experienced with that. But my natural language description should give an insight for what actually needs to go on the query)
Update: On second thought, I don't believe my query will work for all cases. Consider this:
A --> B --> D --> E --> F
F is a descendant of D (True)
E is a parent of F (True)
E is not B (True)
A is not an ancestor of E (False)
Thus, A >> F won't be removed, even though it should. Sorry I couldn't help, but that seems a problem too big to fit in a single query. I'd suggest looking for an algorithmic solution first, then seeing how that could be implemented in your case.
While tracking depth and allowing multiple parents at the same time is probably possible, I get a code smell from it, especially when the solution involves having duplicates pairs. Thomas' answer outlines that issue.
I'm going to simplify the question a bit to just focus on unlinking a node when multiple parents are allowed, because it's a tricky enough problem on its own. I'm discarding the depth column entirely and assuming there are no duplicate pairs.
You have to take into account children of D, which gets complicated fast. Say we have:
A --> B
| |
v v
C --> D --> E
We want to unlink D from B, which means we also have to remove links between E and B. But what if they're connected like this:
A --> B --> C
| |
v v
D --> E < -- G
|
V
H --> F
In this case if we disconnect B > D, we don't want to unlink B and E anymore, because E is still linked to B through C. But we do want to disconnect F from B.
I'll go through my solution below using that second example. I know that D only has one parent in this example, but it still works perfectly if D has multiple parents; I can more easily demonstrate some of the edge cases this way so that's why I'm doing it like this.
Here's what the table would look like:
| Ancestor | Descendant |
-------------------------
| A | A |
| A | B |
| A | C |
| A | D |
| A | E |
| A | F |
| B | B |
| B | C |
| B | D |
| B | E |
| B | F |
| C | C |
| C | E |
| D | D |
| D | E |
| D | F |
| E | E |
| F | F |
| G | G |
| G | E |
| H | H |
| H | F |
Query 1: Get all descendants of D, including D
SELECT `Descendant`
FROM `Closure`
WHERE `Ancestor` = #Node
This will return: D, E, F
Query 2: Get all ancestors of B, including B
SELECT `Ancestor`
FROM `Closure`
WHERE `Descendant` = #ParentNode
This will return: A, B
Query 3a: Get all ancestors of the items in Query 1 that do not appear in Query 1 or 2
SELECT DISTINCT `Ancestor`
FROM `Closure`
WHERE `Descendant` IN (#Query1)
AND `Ancestor` NOT IN (#Query1)
AND `Ancestor` NOT IN (#Query2)
This will return: C, G, H
The goal here is to get all parents of E and F that may reconnect farther up the chain.
Query 3b: this is exactly the same as Query 3a, except it returns both ancestors and descendants
SELECT DISTINCT `Ancestor`, `Descendant`
[ ... ]
This will return: (C, E), (G, E), (H, F)
We'll need this later.
Query 4: Filter results of Query 3a down to nodes that reconnect farther up the chain
SELECT `Ancestor`,`Descendant`
FROM `Closure`
WHERE `Descendant` IN (#Query3a)
AND (`Ancestor` IN (#Query2) OR `Ancestor` = `Descendant`))
This will return: (A, C), (B, C), (C, C)
We now have references to all parents of C that should not be unlinked. Note that we have no links to parents of F. That's because F is not connected to B and A except through D (which we're unlinking).
Query 5: Construct the pairs that should be kept, using the results of Query 3b as a bridge between Queries 1 and 4
SELECT `Query4`.`ancestor`,`Query3b`.`descendant`
FROM (#Query3b) as `Query3b`
LEFT JOIN (#Query4) as `Query4`
WHERE `Query3b`.`descendant` IN (#Query1)
This will return: (A, E), (B, E)
Query 6: Run the regular query for orphaning a node and its children, except exclude all pairs returned by Query 5
DELETE FROM `Closure`
WHERE `Descendant` IN (#Query1)
AND `Ancestor` IN (#Query2)
AND (`Ancestor`, `Descendant`) NOT IN (#Query5)
After this operation, we will have removed the following links:
| Ancestor | Descendant |
-------------------------
| A | D |
| A | F |
| B | D |
| B | F |
Both D and F are correctly unlinked, and E correctly retains its connections to A and B, leaving:
A --> B --> C
|
v
D --> E < -- G
|
V
H --> F
Let me know if I've missed anything! I just solved this problem myself today and I may run into more edge cases as time goes on. If I find any I'll update this answer.