yacc expert? rule useless in parser due to conflicts - Page 1
Forum section: electronics / general

author: legacy
author_rank: Super Contributor
timestamp: February 10, 2019, 10:52:37 pm
content: Code:prog: lines;lines: { list_line(); unknown = dcflag = 0; } /* reset flags */| line { list_line(); unknown = dcflag = 0 ; } /* on every new line */| lines '\n' { list_line(); unknown = dcflag = 0; }| lines line { list_line(); unknown = dcflag = 0; }| lines error { list_line(); unknown = dcflag = 0; };line:| defsym /* define symbol (label) */| stmnt /* opcode */| defcon /* build-in defines */| skip /* comment... */| prepro /* preprocessor command */| END '\n' { return(0); };Code:ass_pars.y:78.5: warning: rule useless in parser due to conflicts [-Wother]line:^cannot understand what is wrong

author: sokoloff
author_rank: Super Contributor
timestamp: February 10, 2019, 11:29:12 pm
content: I'm no yacc expert (and that's putting thingsmildly!), but I think your problem is that you have one too many "or"s in both lines and line, which makes for an ambiguous grammar.Try this:Code:%token defsym stmnt defcon skip prepro END%%prog: lines;lines: { list_line(); unknown = dcflag = 0; } /* reset flags */line { list_line(); unknown = dcflag = 0 ; } /* on every new line */| lines '\n' { list_line(); unknown = dcflag = 0; }| lines line { list_line(); unknown = dcflag = 0; }| lines error { list_line(); unknown = dcflag = 0; };line:defsym /* define symbol (label) */| stmnt /* opcode */| defcon /* build-in defines */| skip /* comment... */| prepro /* preprocessor command */| END '\n' { return(0); };%%

author: sokoloff
author_rank: Super Contributor
timestamp: February 10, 2019, 11:44:25 pm
content: Thinking about it a bit more, you might want to allow a line to be empty, but not a lines.(And since a lines could just be a line, you'll get the same end result, but without the grammar ambiguity.)

author: rhb
author_rank: Super Contributor
timestamp: February 10, 2019, 11:54:28 pm
content: For openers that is not valid syntax. That section should be enclosed by lines which read:%%your stuff%%Besides that you have not defined your tokens;QuoteTry this:Code:%token defsym stmnt defcon skip prepro END%%prog: lines;lines: { list_line(); unknown = dcflag = 0; } /* reset flags */| line { list_line(); unknown = dcflag = 0 ; } /* on every new line */| lines '\n' { list_line(); unknown = dcflag = 0; }| lines line { list_line(); unknown = dcflag = 0; }| lines error { list_line(); unknown = dcflag = 0; };line:| defsym /* define symbol (label) */| stmnt /* opcode */| defcon /* build-in defines */| skip /* comment... */| prepro /* preprocessor command */| END '\n' { return(0); };%%QuoteThat's pretty typical output.I have not used lex and yacc in 27 years, so to say I'm rusty would be an understatement. In fact, about this time 27 years ago I was wrapping up 6 weeks spent learning lex and yacc..A few weeks later I got my first contract job with a major oil company. As it happened my first assignment was a parser. I finished it in 2 weeks working about 1/2 time and doing other things the rest of the time. The project leader had allocated 2 months for the parser. From then on I walked on water.What are you using for a reference? "The Unix Programming Environment" by Kernighan and Pike has a good intro to lex and yacc. I have several feet of books on compilers, regular expressions, parsers etc. So I can only guess what I used 27 years ago besides K&P. But these look likely:Introduction to Compiler Construction with UnixSchreiner & FreemanLex & YaccLevine, Mason & BrownI strongly urge you to work through the 4 banger calculator in K&P.

author: legacy
author_rank: Super Contributor
timestamp: February 11, 2019, 12:32:57 am
content: Code:prog: lines;lines: { list_line(); unknown = dcflag = 0; } /* reset flags */| line { list_line(); unknown = dcflag = 0 ; } /* on every new line */| lines '\n' { list_line(); unknown = dcflag = 0; }| lines line { list_line(); unknown = dcflag = 0; }| lines error { list_line(); unknown = dcflag = 0; };line:| defsym /* define symbol (label) */| stmnt /* opcode */| defcon /* build-in defines */| skip /* comment... */| prepro /* preprocessor command */| END '\n' { return(0); };it seems sensible to TABs, Now, it compiles without wornings, but the whole source.y needs to be rewritten in a neat way.Code:# makeyaccompiling ass_pars.ycompiling ass_pars.ccompiling main.ccompiling misc.ccompiling symbol.ccompiling ass_lex.cbuilding out/as11it's an assembly compiler. For the next project, I will consider above-suggested books.Thanks, guys

author: sokoloff
author_rank: Super Contributor
timestamp: February 11, 2019, 12:43:22 am
content: Don't start every rule with a pipe.Right now a "nothing" matches both the lines and line rules. You don't want that.I think you might also want to allow a blank line to be a line (and so it would match as a lines and a line and not a lines and a '\n', thereby deleting the lines '\n' rule)

author: rhb
author_rank: Super Contributor
timestamp: February 11, 2019, 04:02:50 am
content: Quote from: sokoloff on February 11, 2019, 12:43:22 amIt's *not* a pipe. BNF notation is *not* the Unix shell!!!! The "|" is an "or" in yacc.It's an allowed instance. In regular expression notation it's the equivalent of '(A|B|C|D)' written differently.

author: sokoloff
author_rank: Super Contributor
timestamp: February 11, 2019, 12:55:31 pm
content: Quote from: rhb on February 11, 2019, 04:02:50 amIt sure as hell is a pipe character! That it's not a Unix pipe (nor a copper pipe) is irrelevant.Quote from: rhb on February 11, 2019, 04:02:50 amNo shit; really? I had no idea. I must have just accidentally mistyped when I called it an "or" in my first response, which then seemed to be not clearly understood, so I called the character in concern a "pipe" in the later response to draw attention to the change I made to eliminate the ambiguous grammar rule warning:Quote from: sokoloff on February 10, 2019, 11:29:12 pmQuote from: rhb on February 11, 2019, 04:02:50 amAgreed (and previously understood). The concern is that the rules above have (|A|B|C|D) being a "lines" and (|E|F|G|H) being a "line", with the leading empty case on both, which leads to ambiguity in the grammar.

author: legacy
author_rank: Super Contributor
timestamp: February 11, 2019, 01:48:06 pm
content: Code:prog: lines;lines:/* empty line */ { list_line(); unknown=0; dcflag=0; }/* on every new line */// | line { list_line(); unknown=0; dcflag=0; }| lines '\n' { list_line(); unknown=0; dcflag=0; }| lines line { list_line(); unknown=0; dcflag=0; }| lines error { list_line(); unknown=0; dcflag=0; };line:defsym /* define symbol (label) */| stmnt /* opcode */| defcon /* build-in defines */| skip /* comment... */| prepro /* preprocessor command */| END { return(0); }// | END '\n' { return(0); };does this look better? it compiles without warning, and the resulting compiled module passes all the test cases.Code:; do you like a comment?PORTA equ $00 ; Port A Date RegisterPACTL equ $26 ; Port A Control RegisterSPCR equ $28 ; Control RegisterBAUD equ $2b ; SCI Baud Rate RegisterSCSR equ $2e ; SCI Status RegisterSCDAT equ $2f ; SCI Date RegisterHPRIO equ $3c ; Mode Registeroffset equ $a0 ; startlen equ $a2 ;org $0000 ;getbyte brclr #$20,SCSR,x,* ;ldaa SCDAT,x ;staa 0,y ;ldaa 0,y ;inybrclr #$c0,SCSR,x,* ; Tranceiver Readystaa SCDAT,x ; Echortsdelay ldy #$ffffdelayloop deynopbne delaylooprtsendThe grammar understands the source, and the compiler is correctly able to compile it.(yes, I know there is GNU AS, GAS/11, but it's not directly compatible with Motorola Macro Assembly/11)

author: sokoloff
author_rank: Super Contributor
timestamp: February 11, 2019, 02:04:23 pm
content: Quote from: legacy on February 11, 2019, 01:48:06 pmYup looks good.Quote from: legacy on February 11, 2019, 01:48:06 pmGood deal!

author: legacy
author_rank: Super Contributor
timestamp: February 11, 2019, 09:09:01 pm
content: it has a defectthis worksCode:org $0000anda #$00endthis does not workCode:org $0000anda #$00endfile guineapig2.s (1): syntax errororg $0000lines must begin with a space, otherwise the yy_lex doesn't work correctly.

author: mrflibble
author_rank: Super Contributor
timestamp: March 04, 2019, 01:33:25 am
content: Quote from: legacy on February 11, 2019, 09:09:01 pmDisclaimer:It's been a few years since I last lexed a yacc.Now with that out of the way ...In the definition oflines, the handling of newline struck me as somewhat odd. When you get a situation like this where whitespaces are required at the start/end of line, without this being the design intent, that's usually a hint. The hint being that maybe the handling of newlines and whitespaces might need some attention.Code:lines:/* empty line */ { list_line(); unknown=0; dcflag=0; }/* on every new line */// | line { list_line(); unknown=0; dcflag=0; }| lines '\n' { list_line(); unknown=0; dcflag=0; } // <== That one.| lines line { list_line(); unknown=0; dcflag=0; }| lines error { list_line(); unknown=0; dcflag=0; };Is there a specific reason you want that newline there? To the innocent bystander this comes across as organically grown code. Especially since later on in the definition oflineyou are playing around with '\n' as well.Code:line:defsym /* define symbol (label) */| stmnt /* opcode */| defcon /* build-in defines */| skip /* comment... */| prepro /* preprocessor command */| END { return(0); } // <== Here.// | END '\n' { return(0); } // <== And here.;Since the full code is not included there is no way to be sure, but I suspect that handling of whitespace and newlines with regard to tokenization might need a bit of polish.