I'm building this grammar for a simple programming language (already solved previous ambiguity issues: Can't figure out why Bison is throwing "Rules useless in parser due to conflicts").
This is my complete grammar: http://pastebin.com/yBHLSP0z
And this is the output file from Bison: http://pastebin.com/eAma3gWy
(sorry, they're in Spanish, but I think they're pretty self-explanatory)
The thing is, I'm still getting one shift/reduce error at state 107 (I'm translating it):
state 107
31 factor: ID .
48 concatenacion: ID . OPERADOR_SUMA ID
49 | ID . OPERADOR_SUMA literal_string
OPERADOR_SUMA shift and go to state 140
OPERADOR_SUMA [reduce using rule 31 (factor)]
$default reduce using rule 31 (factor)
Now, state 107 is called from state 70:
estado 70
45 asignacion: ID OPERADOR_ASIGNACION . concatenacion
46 | ID OPERADOR_ASIGNACION . expresion
47 | ID OPERADOR_ASIGNACION . literal_string
OPERADOR_RESTA desplazar e ir al estado 55
PARENTESIS_ABRE desplazar e ir al estado 56
COMILLA desplazar e ir al estado 67
ID desplazar e ir al estado 107
expresion ir al estado 108
termino ir al estado 61
factor ir al estado 62
concatenacion ir al estado 109
literal_string ir al estado 110
literal_real ir al estado 63
literal_entero ir al estado 64
signo ir al estado 65
What I think is happening (please correct me if I'm wrong) is that when it finds a rule for "asignacion" like this:
asignacion: ID OPERADOR_ASIGNACION concatenacion | ID OPERADOR_ASIGNACION expresion
it sees that from "expresion" it can get an ID token (expresion > termino > factor > ID), making a ID OPERADOR_ASIGNACION ID:
expresion:
expresion OPERADOR_SUMA termino
| expresion OPERADOR_RESTA termino
| termino
;
termino:
termino OPERADOR_MULTIPLICACION factor
| termino OPERADOR_DIVISION factor
| factor
;
factor:
ID
| literal_entero
| literal_real
| PARENTESIS_ABRE expresion PARENTESIS_CIERRA
;
Now, when it reaches an ID OPERADOR_ASIGNACION concatenacion and looks at the rules for "concatenacion", it gets:
concatenacion:
ID OPERADOR_SUMA ID
| ID OPERADOR_SUMA literal_string
| literal_string OPERADOR_SUMA ID
| literal_string OPERADOR_SUMA literal_string
;
Two of them begin with "ID". So if any of those two rules are selected, it gets to a state where it can obtain a ID OPERADOR_ASIGNACION ID, only that with the "concatenacion" rules, it needs to find a "OPERADOR_SUMA" token afterwards. But I believe it's choking as soon as it sees that from both "concatenacion" and "expresion" can form the ID OPERADOR_ASIGNACION ID expression.
If this is not exactly what's going on, I'd like to know what is then the problem.
And, if I'm correct as where the error happens, I really don't know how to solve it.
Please help :)
Thanks!
The problem arises from:
asignacion
: ID OPERADOR_ASIGNACION concatenacion
| ID OPERADOR_ASIGNACION expresion
;
and the selected alternatives:
expresion
: expresion OPERADOR_SUMA termino
;
termino
: factor
;
factor
: ID
;
concatenacion
: ID OPERADOR_SUMA ID
;
Which means that when your parser encounters:
x = y + z
it cannot tell whether it is processing the first or second alternative for asignacion.
That's the easy part. How to fix? The simplest fix (if it works, which I've not tested) would be to remove the concatenacion rule I showed, and in the expresion rule, recognize when you are dealing with a concatenacion vs an expresion since they are syntactically identical:
ID OPERADOR_SIGNACION ID OPERADOR_SUM ID
You'd look at the types of the two operands of the expresion, and if they are both string types, then you'd assume it was a concatenacion, otherwise an expresion.
You might want to review the whole of the concatenacion rule, though. You'd need to let strings through the factor rule, I think, so you'd add another alternative to factor:
factor
: literal_string
;
It would mean you'd have to reject literal strings in other rules, though, so more semantic checking. An alternative is to introduce a separate operator other than + to mean 'string concatenation'. SQL uses ||; some languages have used ,; you could use another token altogether, such as #. There are many options once you break away from +. Can you even just use 'two adjacent string expressions mean the concatenation operation', with no operator between them?
If none of that works, then get back to me.
Related
I'm working on remove left recursion in grammar. (3 grammars)
1. A->Ab | aC
B->BaBB | BA
C->bC | BA
2. T->Txxy | TaabT | TTa
3. A-> BA | Baa
B-> Ab | Abb
I've tried to do it, but I'm not sure about my answers.
First one, I have no idea how to do it. Second, the third one I think it will fail. Is my answer right?
How can I change that?
Please someone explain it in detail.
I have written the solution. I didn't have much time to type the entire thing and also I was not sure if this question will be available anymore because of offtopic.
Check the solution for first grammar here at first grammar solution
For the second grammar, either the Grammar is incomplete or left recursion can't be removed, there is no null production nor it has any production with only terminals. It is infinitely recurring and hence can't remove left recursion.
For the third grammar, we can do
A-> BA | Baa
B-> Ab | Abb
Replace All B's into A
A-> AbA | Abaa | AbbA | Abbaa
Now again all the productions are recursive and can't even terminate the grammar. You either need a null production or a production with only terminals.
I am looking for assistance in finding records that have a reoccurring string/number in an attibute due to input mismanagement. For example, the table will look similar to the following:
ID|stuff
1 | 23 jackson jackson st
2 | 89 jackson st
3 | 1 1 jackson st
4 | 66 jackson st
I'd like the return to look like the following:
ID|stuff
1 | 23 jackson jackson st
3 | 1 1 jackson st
please note, in the above example, 's' doesnt cause it to return in id 2, even though its in both jackSon and St.
Any help would be greatly appreciated, thank you.
You can use back-references in Oracle regular expressions. I think this does what you want:
select *
from t
where regexp_like(' ' || stuff, ' ([^ ]+) .*\1');
Here is a db<>fiddle.
Use this WHERE predicate
where regexp_like(stuff, '(^|\W)(\w+)($|\W).*\2')
Note that initial and traling group (^|\W) and ($|\W) means start/ end of the string or a non-word charater will delimit the second group - the first instance of the duplicated word.
The second group is defined as a (\w+) one or more word charters.
You may want alternatively use \s (white space) instead of \W - see here for further details.
Here sample data returned by this regexp addressing also the non-word delimiters.
You should also not underestimate tabs and other white stuff, that the simple solution ignore.
23 jackson jackson st
1 1 jackson st
68 jackson.st.jackson
See also this answer with a similar topic.
I searched, but seems I haven't found the right keyword for describing what I am trying to achieve, so please be lenient if this is a known problem, just point me to the right keywords.
I have following tables/entries:
select * from personnes where id=66;
id | aclid | referendid | login | validated | passwd
66 | | | toto#tiiti.com | f | $2y$10$w3DRh/g2Tebu/mkMcQz32OUB.dDjFiBP99vWlMrrPWpR45JZDdw4W
and
select * from pattributs where (name='nom' OR name='prenom') AND persid=66;
id | name | value | persid
----+--------+-------+--------
90 | prenom | Jean | 66
91 | nom | Meyer | 66
Now I use that form for not cluttering the main table, since depending on the case, I record the name, or not....
but having a view as a table of the completed table would be nice, so I tried:
select (personnes."id","login",
(select "value" from pattributs where "name"='nom' AND "persid"=66),
(select "value" from pattributs where "name"='prenom' AND "persid"=66)
) from personnes where personnes.id=66;
which seems to do the job:
row
--------------------------------
(66,toto#tiiti.com,Meyer,Jean)
but the column tags disappeared, and being able to fetch them from the invoking php script is immensely useful, but when I add:
select (personnes."id","login",
(select "value" from pattributs where "name"='nom' AND "persid"=66),
(select "value" from pattributs where "name"='prenom' AND "persid"=66) as 'prenom')
from personnes where personnes.id=66;
I get a syntax error at the as directive... So probably I haven't understood how to do this properly, the braces indicate that this isn't anymore in tabular form), so how can I achieve the following result:
id | login | nom | prenom
66 |toto#tiiti.com | Meyer | Jean
The idea being to store a suitable view for each use case, bundling only the relevant columns.
Thanks in advance
To answer your question: You are loosing the column names because you are creating a simple data set, a row. This is done by your braces. Without them you should get your expected result.
But your solution is not very well: You should avoid to calculate your single columns in every single subquery. This could be done easily in one SELECT:
select
pe.id,
pe.login,
MIN(pa.value) FILTER (WHERE pa.name = 'nom') as nom,
MIN(pa.value) FILTER (WHERE pa.name = 'prenom') as prenom
from
personnes pe
join pattributs pa ON pe.id = pa.persid AND pe.id = 66
where pa.name = 'nom' or pa.name = 'prenom'
group by pe.id, pe.login
First you'll need a JOIN to get the right datasets of both tables together. You should join on the id.
Then you have the problem that you have two rows for the name (which seems not very well designed, why not two columns?). These two values can be grouped by the id. Now you could aggregate them.
What I am doing is to "aggregate" them (it doesn't matter what function I am using because it should be only one value). The FILTER clause filters out the right value.
I update a View to get in two columns the same value, but it interchanges the two values instead of just setting it. My (reduced for so) view UpdateADAuftrag2 is this.
SELECT dbo.CSDokument.AD1, dbo.UpdateAS400zuSellingBenutzer2.BenutzerNr
FROM dbo.AS400Auftrag
INNER JOIN
dbo.CSDokument ON dbo.AS400Auftrag.Angebotsnummer = dbo.CSDokument.Angebotsnummer
INNER JOIN
dbo.UpdateAS400zuSellingBenutzer2 ON dbo.AS400Auftrag.AD = dbo.UpdateAS400zuSellingBenutzer2.SchluesselWert
AND
dbo.CSDokument.AD1 <> dbo.UpdateAS400zuSellingBenutzer2.BenutzerNr
WHERE (dbo.AS400Auftrag.AD IS NOT NULL)
The important part is dbo.CSDokument.AD1 <> dbo.UpdateAS400zuSellingBenutzer2.BenutzerNr
AD1 is user number for external workers and BenutzerNr means user number. So e.g. the person Charlie Brown is an external worker and has the user number 31. When in AD1 is 31 - Charlie Brown is the external worker for this document (order in this case).
The Update statement loos like this
UPDATE [dbo].[UpdateADAuftrag2]
SET [AD1] = [BenutzerNr]
I have for example these values
AD1 | BenutzerNr
31 | 54
99 | 384
112 | 93
after the update the result is this
AD1 | BenutzerNr
54 | 31
384 | 99
93 | 112
Why not this?
AD1 | BenutzerNr
54 | 54
384 | 384
93 | 93
edit: UpdateAS400zuSellingBenutzer is also a View, but as far as I can see it includes only BenutzerNr and not AD1.
Firstly, you're never going to see your expected results in the view. Your UPDATE statement is effectively a DELETE statement (as far as the view is concerned). Rows only appear in the view if AD1 <> BenutzerNr, but you're setting them to be equal.
However, the documentation for updatable views states "Any modifications, including UPDATE, INSERT, and DELETE statements, must reference columns from only one base table." Your update statement references columns from more than one table.
https://msdn.microsoft.com/en-us/library/ms187956.aspx#Updatable Views
I'm not sure what you're trying to achieve here, but in my experience it's usually easier to issue the UPDATE statement against the base tables directly.
There were 2 bugs - Bug 1 View UpdateAS400zuSellingBenutzer2 had 2 results sometimes for one entry in CSDokument and Bug 2 There were 2 entries in Table AS400Auftrag and then it switched between these two entries. So it just looked like the SET switched the two entries but it was just by chance. Thanks for reading.
I'm kinda new to RDP/Pairwise Disjoint Test and this is just a sample problem. I already have the answer and I would just like to verify if this is correct.
Grammar:
<GU> ::= du<GU>bi<MI> | <HO> | ru
<MI> ::= ra | fa | <HO>
<HO>::= bi<HO> | bi
Solution:
will generate a sting of "bi" OR one "bi"
will generate one "ra" OR one "fa" OR (string of "bi" OR one "bi")
So will generate
du <GU> bi {ra | fa | {bi's | bi} } | {bi's | bi} | ru
Here are the sentences that can be produced by the grammar:
a. dudurubifabira
b. dubibibira
c. dubirubirurafa
d. dududubibibifabirabibibi
e. dududubibifarabirabibi
My answer is "b" and "d".
Am I correct?
Looks like a can also be generated by the language:
<GU>
-> du<GU>bi<MI>
-> dudu<GU>bi<MI>bi<MI>
-> dudurubi<MI>bi<MI>
-> dudurubifabi<MI>
-> dudurubifabira
Otherwise, your end result seems to be correct. I'd be careful about saying a "bi" will generate something though, since it's a terminal.