if-else statement in bison - if-statement

I'm trying to do the if-then statement in bison. The problem is that im working on a solution that everyone says that is working, but it doesnt :( my code is:
statement : matchedstmt
| unmatchedstmt
;
matchedstmt : if '(' expression ')' matchedstmt else matchedstmt
| otherstmt
;
unmatchedstmt : if '(' expression ')' statement
| if '('expression ')' matchedstmt else unmatchedstmt
;
otherstmt : expressionstmt
| compoundstmt
| iterationstmt
| returnstmt
;
...
where "if" & "else" are %token
!! in terminal it says that i have one shift/reduce.
I also tried %nonassoc and %left
what can i do??

The following can be processed by bison with no conflicts of any kind:
statement : matchedstmt
| unmatchedstmt
;
matchedstmt : if '(' expression ')' matchedstmt else matchedstmt
| otherstmt
;
unmatchedstmt : if '(' expression ')' statement
| if '('expression ')' matchedstmt else unmatchedstmt
;
otherstmt : expressionstmt
| compoundstmt
| iterationstmt
| returnstmt
;
That's unsurprising since you are using a standard mechanism for disambiguating the if ... else statement.
Presumably, the shift-reduce conflict is somewhere else in your grammar, possibly involving an interaction with this fragment. I suggest you add more statement types one at a time until you find the rule which causes the conflict. Unfortunately, LR grammars do not compose well: it is quite possible for two perfectly conflict-free fragments to produce a conflict when they are combined in a grammar.
On the whole, you will find that you will get better answers on StackOverflow if you follow the guidelines in How to ask. In particular, you should first attempt to find the smallest program which exhibits the problem you are expriencing, and then put all of that into your question. That is what we call a MCVE: Minimal, Complete, and Verifiable example, which has the advantage that someone attempting to answer your question can see exactly what you are doing.
An extract from your code which cannot be compiled or executed is not an MCVE. Creating an MCVE might seem like a lot of work, and sometimes it is. But aside from helping people to answer your question, it also helps you to answer your own question, because it helps you focus on the problem. So it's a very useful exercise.

the best way for solve this problem using %nonassoc.
%nonassoc THEN
%nonassoc ELSE
%%
statement: TIF TLPAREN expression TRPAREN TTHEN statement %prec THEN
| TIF TLPAREN expression TRPAREN TTHEN statement TELSE statement
%%

Related

Repeat expression until it has reached the end of parenthesis?

I have been working in Regx101 and have been messing around with expressions however I cannot figure out how to repeat an expression until a certain character (ending parenthesis ')' ) is reached.
I have tried [^)]* and it works but it does not repeat the expression.
This is my expression so far:
CREATE\s+TABLE\s+(\w*)(\s+(\w*)\s+(\w*)[,][^)]*
I am trying to get the (\s+(\w*)\s+(\w*)[,] part to repeat until the end of a parenthesis is reached.
My test string is:
CREATE TABLE tableName(columnName, type, primary, columnName2, type2)
These are the results I am getting:
enter image description here
Expected results should include column2 and type2 as their own individual group.
Any help is welcomed as well as any solutions I have not tried yet.
Not completely sure what exactly you want, but this example
echo 'CREATE TABLE tableName(columnName, type, primary, columnName2, type2)' \
| perl -nle '/CREATE\s+TABLE\s+(\w*)\s*\((\s*(\s*\w+ *,)+(\s*\w+)?)/ && print "$1\n$2"'
or this slightly more readable version with the /x modifier
echo 'CREATE TABLE tableName(columnName, type, primary, columnName2, type2)' \
| perl -nle '/CREATE\s+TABLE\s+(\w*) \s* \( (\s*(\s*\w+\s*,)+ (\s*\w+)? )/x && print "$1\n$2"'
give this output
tableName
columnName, type, primary, columnName2, type2

Lex: Avoid a quoted expression

I'm trying to build a lex program which should avoid a quoted sequence of characters. Something like not(":="). I've written this so far but can't seem to be able to get the desired output:
/* Definitions */
assgn ":="
symbol [^{assgn}]
%%
.
":=" {printf("Found - %s\n",yytext);}
{symbol} {printf("Error: Unmatched symbol \'%s\'\n", yytext);}
%
Input:
:= & | #
Output:
Found - :=
Error: Unmatched symbol ':'
Error: Unmatched symbol '='
Error: Unmatched symbol '&'
Error: Unmatched symbol '|'
Error: Unmatched symbol '#'
Desired output:
Found - :=
Error: Unmatched symbol '&'
Error: Unmatched symbol '|'
Error: Unmatched symbol '#'
I want that the program avoids the ":=" as a whole but it still reads the single character ":". How do I correct this?
The following little complete (f)lex program does precisely what is desired. flex will not rescan a matched token unless you ask it to (or, of course, there is some undefined behaviour in your code which corrupts flex's internal data structures.)
%{
#include <stdio.h>
%}
%option nodefault noyywrap noinput nounput
%%
[[:space:]]+ /* Ignore spaces */
":=" {printf("Found - %s\n",yytext);}
. {printf("Error: Unmatched symbol \'%s\'\n", yytext);}
With the above file stored in only:=.l, I do the following:
$ lex -o only:=.c only:=.l
$ gcc -o only:= -Wall only:=.c -lfl
$ ./only:=
:= & | #
Found - :=
Error: Unmatched symbol '&'
Error: Unmatched symbol '|'
Error: Unmatched symbol '#'
(-lfl adds a minimal definition of main())

How to eliminate left recursion in context-free grammar?

How would I eliminate the left recursion in this CFG?
<RE> -> <RE>'|'<CONCAT> | <CONCAT>
<CONCAT> -> <CONCAT><KLEEN> | <KLEEN>
<KLEEN> -> <KLEEN>'*' | <ELEM>
<ELEM> -> 'a' | 'b' | 'c' | 'd' | '('<RE>')'
Have a look at the section on Removing Left Recursion on Wikipedia.
Theres an description of exactly how to do it, following of;
Moore, Robert C. (May 2000). "Removing Left Recursion from Context-Free Grammars" . 6th Applied Natural Language Processing Conference: 249–255. http://aclweb.org/anthology-new/A/A00/A00-2033.pdf .

how to exactily repeat the n matched pattern in result string

How to exactly repeat the n matched pattern in result string?
Example if I have the folowing text:
++ '[' -f /etc/bashrc ']'
++ . /etc/bashrc
+++ '[' '[\u#\h \W]\$ ' ']'
+++ '[' -z 'printf "\033]0;%s#%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"' ']'
+++ shopt -s checkwinsize
+++ '[' '[\u#\h \W]\$ ' = '\s-\v\$ ' ']'
+++ shopt -q login_shell
+++ '[' 506 -gt 199 ']'
++++ id -gn
Now I want to substitute every '+' for 3 spaces, but it can only happen at the begining of the pattern. I would use :<range>s/^<pattern> :%s/+/ /g, but if it there were a '+' in the rest of the text I would simply mess it up.
The question:
How to match every + at begining and repeat the same count of found + in the result string?
expected:
^ ++$ -> ^ $
^ +++$ -> ^ $
^ +$ -> ^ $
Thanks
Try this:
:%s/^+*/\=repeat(' ',strlen(submatch(0)))/
submatch(0) contains all the matched + at the start of the line, strlen counts them. So for every plus sign at the start of the line three spaces are inserted using repeat.
For more information:
:help sub-replace-expression
:help repeat()
:help submatch()
:help strlen()
An elegant substitution command for this case is the following:
:%s/\%(^+*\)\#<=+/ /g
I think you'll have to run an expression several times, if that is acceptable...
You'll want to run something like this (minus the single quotes, which are used to show whitespace):
'^(\s*)+'
replacing with something like (again minus the single quotes)
'$1 '
Not every problem that can be solved with regular expressions can be solved using only a single regular expression - I'm pretty sure this is one of those cases
This expression/replacement pair will need to be run once for each plus sign at the beginning of the line with the most plus signs (in your example above, that would be four times) N.B.: as written, this will mess up any lines that are supposed to begin with whitespace and plus signs , so I hope that doesn't happen anywhere...

(f)lex can you have multiple expressions in one state?

is it possible to have multiple expression in one state that are similar? I was hoping to group together a few expressions to make life easy for myself. i want to do something similar below but its not working and only recognise the 1st expr and although it does match the expr it doesnt save into the array using yytext. im guessing im doing something wrong so any help would be appreciated.Thanks
<some_state>"Milk;" |
"Honey;" |
"Cinnamon;" |
"Cardamon;" |
"Rum;" |
"Brandy;" |
"Whiskey;" |
"Aquavit;" |
"Kahula;" { printf("Example"); array[i].addition = yytext;BEGIN(amount_state);}
If flex is allowed, you can use start condition scope like the following:
<some_state>{
"Milk;" |
"Honey;" |
... |
"Kahula;" { printf("Example"); ... }
}
If only AT&T lex is allowed, unfortunately this may be invalid...