cs326ad@ux1.cso.uiuc.edu (02/24/90)
Here's an interesting question that I pose to people who are familiar with lex and/or flex. I am working on a compiler project, and am attempting to do the work at home instead of on the net. The work is being done using Zortech's C++, but I am having a small problem as follows: In (f)lex definitions, we define whitespace as ws [ \t\n] That is, ws is any one of _blank_, tab, or newline. If lex runs across this in the input file, then it takes an appropriate action (in my case, none.) Now, when porting this code to C++ zortech style, the lex.yy.c program compiles fine (with a few minor changes.) However, the executable does NOT recognize the \n the same as the executable on the net. i.e.: If we input: 1234 to the lex executable on the net, I get the output INT 1234 However, on the zortech implementation, for the same input, I get INT 1 Doing a little debugging on the zortech code, I came to realize that the eoln was ended with a \r\n for carriage return newline. Fine. But for some reason the zortech implementation does not catch the newline at the end of the line, like it does on the net. In addition, I compiled the lex code with Microsoft 5.01, and the program worked fine. Same code, different compiler. There just seems to be an odd quirk with the zortech implementation of eoln (at least in this case) since all the lex code does is scan for certain tokens appearing in the input, and when it matches a token, it performs a given action. So, the bottom line question is why, with the same code from the same lex file, I get two different executables from two different compilers. I hope that this explaination is clear enough. It is kind of a tough problem to explain. Any helpful insight would be appreciated. =========================================================================== = = = Mark Allender University of Illinois = = cs326ad@ux1.cso.uiuc.edu Urbana, Illinois = = ma20449@uxa.cso.uiuc.edu = = = ===========================================================================
bright@Data-IO.COM (Walter Bright) (02/25/90)
In article <6300008@ux1.cso.uiuc.edu> cs326ad@ux1.cso.uiuc.edu writes:
<Now, when porting this code to C++ zortech style, the lex.yy.c program compiles
<fine (with a few minor changes.) However, the executable does NOT recognize
<the \n the same as the executable on the net. i.e.:
<If we input: 1234 to the lex executable on the net, I get the output
<INT 1234
<However, on the zortech implementation, for the same input, I get
<INT 1
<Doing a little debugging on the zortech code, I came to realize that the
<eoln was ended with a \r\n for carriage return newline. Fine. But
<for some reason the zortech implementation does not catch the newline at
<the end of the line, like it does on the net.
I'm afraid I don't understand. Is the *compiler* not working right or the
*run-time library*? Please reduce the problem to a few lines of code
which exhibit the problem. I know very little about lex/flex.
csu025@umaxc.weeg.uiowa.edu (Kent Williams) (02/27/90)
>I'm afraid I don't understand. Is the *compiler* not working right or the >*run-time library*? Please reduce the problem to a few lines of code >which exhibit the problem. I know very little about lex/flex. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! Yipes! If you don't mind my asking, do you USE any automated compiler writing tools? Maybe I got into the game a little later that you did, but a compiler author who knows little about lex is a little like a auto mechanic who doesn't know about socket wrenches -- I've no doubt he can do his job, but isn't he working a little bit too hard?
meissner@osf.org (Michael Meissner) (02/27/90)
In article <741@ns-mx.uiowa.edu> csu025@umaxc.weeg.uiowa.edu (Kent Williams) writes: | >I'm afraid I don't understand. Is the *compiler* not working right or the | >*run-time library*? Please reduce the problem to a few lines of code | >which exhibit the problem. I know very little about lex/flex. | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! | | Yipes! | If you don't mind my asking, do you USE any automated compiler writing | tools? Maybe I got into the game a little later that you did, but a | compiler author who knows little about lex is a little like a auto mechanic | who doesn't know about socket wrenches -- I've no doubt he can do his | job, but isn't he working a little bit too hard? I have supported three compilers in the last 10 years (DG/L, Data General C, and now GNU C), and none of them use any automatic tools for lexing. First of all, UNIX lex is too general purpose, and too slow to be used in a production compiler (yes I know flex fixes at least some of the speed problems). You don't need backtracing, or even generalized regular expressions, and such for most computer languages to lex stuff, just simple one character lookahead. Second of all, lex-ing is fairly simple. It took me a day or so, to write from scratch the lexer for Data General C. It would have taken more time to come up to speed with lex (ignoring the problem that we didn't have lex at the time) than to just write the code. IMHO if you think writing a lexer is too hard, you have no business writing compilers. -- Michael Meissner email: meissner@osf.org phone: 617-621-8861 Open Software Foundation, 11 Cambridge Center, Cambridge, MA Catproof is an oxymoron, Childproof is nearly so
maxsmith@athena.mit.edu (Samuel M Druker) (02/27/90)
Lex generated scanners are slower than hand crafted ones. Doubly so for yacc and its output and yacc it self can't produce a C++ parser, something to do with the language not conforming to LALR(1) and all that. If you've only got a specialized compiler market, especially a cutthroat one like the DOS world, lex and yacc aren't vital. Samuel Druker
voss@sunb6.cs.uiuc.edu (03/01/90)
> maxsmith@athena.mit.edu writes: > Lex generated scanners are slower than hand crafted ones. Doubly so for > yacc and its output and yacc it self can't produce a C++ parser, something > to do with the language not conforming to LALR(1) and all that. I saw that comment about C++ not being LALR(1) in the g++ distribution, and at the time believed it. However, my biggest thrill at OOPSLA '89 was sitting at the same table as Bjarne Stroustrup for a few hours drinking free beer. He said that he IS USING A LALR(1) GRAMMER for C++ 2.0. He appeared sober & honest, therefore I assume that C++ is LALR(1), but non-trivial. ============================================================================= First, let me make it clear that I am by no means an expert at writing compilers (<grin> yet). I am a graduate student in CS, currently taking my first (much overdue) compiler course. We are using the text _Compilers_Principles_Techniques_and_Tools_ by Aho, Sethi, and Ullman. The programming portion of the class involves using lex/flex and yacc/byacc/bison to implement a subset of Pascal. Now my questions: > meissner@osf.org > Second of all, lex-ing is fairly simple. It took me a day or so, to > write from scratch the lexer for Data General C. It would have taken > more time to come up to speed with lex (ignoring the problem that we > didn't have lex at the time) than to just write the code. IMHO if you > think writing a lexer is too hard, you have no business writing > compilers. No, I don't think writing a lexer is hard. I did it many times before I even heard of lex (though I didn't know I was writing "lexers.") However, I can now write and debug a lexical analyzer in half a day max using flex, and anyone knowing lex/flex could easily maintain my code. Therefore I doubt I will ever write another "lexer" by hand. I think the surprise is that a "commercial compiler writer" would not be familiar with flex/lex. If you don't mind my asking, when did you study compilers, and what text did you use? ============================================================================== > schmidt@zola.ics.uci.edu writes: > Actually, GNU C uses a reserved word recognizer function generated > automatically by my GPERF program. But I understand your general > point. then goes on to give performance figures showing GPERF is much faster than flex/lex. I am not familiar with GPERF. What did you give up to get the speed advantage? Is GPERF available via anonymous ftp? Where? thanks, Bill Voss Email: billvoss@uiuc.edu or voss@cs.uiuc.edu
schmidt@zola.ics.uci.edu (Doug Schmidt) (03/01/90)
There are a number of confusions in your post. Let me see if I can shed some light on this. In article <24800002@sunb6>, voss@sunb6 writes: >I saw that comment about C++ not being LALR(1) in the g++ distribution, >and at the time believed it. However, my biggest thrill at OOPSLA '89 >was sitting at the same table as Bjarne Stroustrup for a few hours drinking >free beer. He said that he IS USING A LALR(1) GRAMMER for C++ 2.0. >He appeared sober & honest, therefore I assume that C++ is LALR(1), but >non-trivial. Your statement confuses the difference between an LALR(1) language (which C++ is *not*) and a particular set of tools used to recognize a language. What Bjarne probably meant (judging from the cfront 2.0 sources) is that he was using the LALR(1) parser generated by yacc to recognize C++. What you probably don't know is that cfront 2.0 also utilizes an infinite-lookahead lexical analyzer (hand-coded, BTW) that enables it to handle the non-LALR(1) parts of the language, e.g. disambiguating between certain type-decls and expressions. Incidentally, Jim Roskind (ileaf!io!bronx!jar@EDDIE.MIT.EDU) has released a beta version of his yacc-based grammar that accepts C++ 2.0 syntax *without* using an infinite lookahead lexer. As far as I know this grammar has not yet been incorporated in any production-quality C++ compiler or translator. Comments Jim? > No, I don't think writing a lexer is hard. I did it many times >before I even heard of lex (though I didn't know I was writing "lexers.") >However, I can now write and debug a lexical analyzer in half a day max >using flex, and anyone knowing lex/flex could easily maintain my code. Have you ever tried writing a f?lex scanner for full ANSI C? There are some surprising subtleties. Henry Spencer posted one to the net a while back. Let me know if you'd like a copy to peruse. It's got `easy to maintain' regular expressions like: L?\'([^'\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|[xX][0-9a-fA-F]+))+\' L?\"([^"\\\n]|\\(['"?\\abfnrtv\n]|[0-7]{1,3}|[xX][0-9a-fA-F]+))*\" >Therefore I doubt I will ever write another "lexer" by hand. Well, if you don't end up working with language processing tools then the point is moot... ;-) On the other hand, what if you write portable programs for systems that lack f?lex? What if you are trying to write a fast lexer in order to gain market share for your product? f?lex are extremely useful for certain purposes, but there are often pragmatic reasons why they aren't used in every circumstance. > I think the surprise is that a "commercial compiler writer" >would not be familiar with flex/lex. Why is that surprising? f?lex scanners are *not* generally used for production (i.e., commercial) compilers. And certainly not in a highly competitive market like MS-DOS! > I am not familiar with GPERF. What did you give up to >get the speed advantage? The trade-off is generality versus specificity. GPERF is a great solution for a particular (and limited) problem domain, i.e., implementing recognizers for static search sets. It doesn't provide anywhere *near* the flexibility of f?lex. De gustibus non disputandum est... >Is GPERF available via anonymous ftp? Where? You bet! (glad you asked... ;-)). The C++ and C version of GPERF is available via anonymous ftp from ics.uci.edu (128.195.1.1) in the ~ftp/pub directory: ---------------------------------------- -rw-r--r-- 1 ftp 120483 Feb 15 23:30 gperf-2.3.tar.Z -rw-r--r-- 1 ftp 97187 Nov 11 14:15 cperf-2.1.tar.Z ---------------------------------------- I'm also presenting a paper on GPERF at the upcoming USENIX C++ Conference in San Francisco. A preliminary draft is also available via ftp from ics.uci.edu: ---------------------------------------- -rw-r--r-- 1 ftp 43820 Feb 18 17:10 gperf.tex ---------------------------------------- I'd be interested in any comments people might have (there's still time to make revisions!) Doug -- The official language of San Marcos is Swedish. All boys | schmidt@ics.uci.edu under the age of sixteen years old are now sixteen years | office (714) 856-4043 old. Underwear must be changed every half hour. It will +---------------------- be worn on the outside, so we can check. -- `Bananas' by Woody Allen
jbuck@henry.berkeley.edu (Joe Buck) (03/01/90)
In article <25EC5CBF.26673@paris.ics.uci.edu> schmidt@zola.ics.uci.edu (Doug Schmidt) writes: >> No, I don't think writing a lexer is hard. I did it many times >>before I even heard of lex (though I didn't know I was writing "lexers.") >>However, I can now write and debug a lexical analyzer in half a day max >>using flex, and anyone knowing lex/flex could easily maintain my code. >Have you ever tried writing a f?lex scanner for full ANSI C? There >are some surprising subtleties. Henry Spencer posted one to the net a >while back. Let me know if you'd like a copy to peruse. It's got >`easy to maintain' regular expressions like: >L?\'([^'\\\n]|\\(['"?\\abfnrtv]|[0-7]{1,3}|[xX][0-9a-fA-F]+))+\' >L?\"([^"\\\n]|\\(['"?\\abfnrtv\n]|[0-7]{1,3}|[xX][0-9a-fA-F]+))*\" This is as ugly as it is because Henry failed to use definitions. Any experienced user of flex would define a symbol to represent letters, a symbol to represent numbers, a symbol to recognize backslash escapes, etc, and build the above expressions out of the symbols. Only someone trying to slam the lex approach would write the above monstrosities. >>Therefore I doubt I will ever write another "lexer" by hand. >Well, if you don't end up working with language processing tools then >the point is moot... ;-) On the other hand, what if you write portable >programs for systems that lack f?lex? Do you have C? Flex generates C code, and is written in C, and is freely redistributable. > What if you are trying to write >a fast lexer in order to gain market share for your product? You certainly wouldn't want to use lex then, but flex is far faster, and other lexer generators are faster still. Check out Van Jacobsen's paper from the 1986 Winter Usenix, where he produced a lexer generator as fast (almost) as cat, and got the inner loop down to one 68000 instruction per character processed (anyone know if this version is ever going to be public?). Beat that with a hand-written lexer. Granted, Vern Paxton's flex program is not this good, but many people got turned off to lexer generators because lex is so horrible. flex is far superior to lex. The "f" stands for "fast", not free. For that reason, writing "f?lex" is unfair to flex, lumping it in with a very inefficient program. -- -- Joe Buck jbuck@janus.berkeley.edu {uunet,ucbvax}!janus.berkeley.edu!jbuck
rfg@ics.uci.edu (Ronald Guilmette) (03/01/90)
In article <25EC5CBF.26673@paris.ics.uci.edu> schmidt@zola.ics.uci.edu (Doug Schmidt) writes: >There are a number of confusions in your post. Let me see if I can >shed some light on this. > >In article <24800002@sunb6>, voss@sunb6 writes: >>I saw that comment about C++ not being LALR(1) in the g++ distribution, >>and at the time believed it. However, my biggest thrill at OOPSLA '89 >>was sitting at the same table as Bjarne Stroustrup for a few hours drinking >>free beer. He said that he IS USING A LALR(1) GRAMMER for C++ 2.0. >>He appeared sober & honest, therefore I assume that C++ is LALR(1), but >>non-trivial. > >Your statement confuses the difference between an LALR(1) language >(which C++ is *not*) and a particular set of tools used to recognize a >language. Doug, I afraid that I have to point out that *your* statement confuses the difference between an LALR(1) language and the patently false assertions that some people have made vis a vis the supposed non-LALR(1)'ness of C++. As was pointed out to me a couple of years ago by a fellow who really should know something about the subject (i.e. Tom Pennello) virtually any language can be considered to be trivially LALR(1) in the sense that the grammar can always be reduced to V* which will accept all legal inputs in the language. Rejection of illegal inputs with such a grammar would necessarily be strictly a matter for semantic analysis. Now it is quite obvious that the use of V* as a grammar to guide an LALR(1) parser would not allow the resulting parser to detect many sorts of errors which we would normally think of as being "syntatic" errors, (like say none) but the division between syntatic and semantic errors is an artificial one and such a grammar, when mashed into pasring tables and combined with a general LALR(1) parser driver, would in fact successfully (if trivially) parse C++, thus clearly indicating that C++ *is* LALR(1). The fact of the matter is C++ is only asserted to be be non-LALR(1) by persons who want to see more constructs in the language be disambiguated via easy-to-implement LALR(1) syntax rules rather than via much harder to implement semantic rules. There is nothing wrong with such a goal. In fact I would say that this is a very important goal. Anybody who has ever had to build a recognizer for C or C++ or FORTRAN or Ada will certainly tell you that it is one hell of a lot easier to disambiguate things via context free syntax rules than it is to do the same job via context sensitive semantic rules. In particular, typedefs have kept many C compiler writers awake at nights thinking about the torturous things they do to feed information backwards from semantic anaysis so that it can be subsequently considered by their (more convenient and more regular) LALR(1) syntax analyzers. So the goal is good. What is *not* good is muddling the issue with meaningless catch phrases like "C++ is not LALR(1)". In order to move the discussion onto a higher plain, let's try to be accurate and just say that it would be nice if an LALR(1) grammar for C++ could allow for much more disambiguation via easy-to-implement LALR(1) syntax rules. >What Bjarne probably meant (judging from the cfront 2.0 >sources) is that he was using the LALR(1) parser generated by yacc to >recognize C++. Free advice: Second guessing Bjarne's intended meaning based on sketchy second-hand accounts is probably inadvisable. // Ron Guilmette (rfg@ics.uci.edu) // C++ Entomologist // Motto: If it sticks, force it. If it breaks, it needed replacing anyway.
bright@Data-IO.COM (Walter Bright) (03/02/90)
In article <741@ns-mx.uiowa.edu> csu025@umaxc.weeg.uiowa.edu.UUCP (Kent Williams) writes:
<<I know very little about lex/flex.
<If you don't mind my asking, do you USE any automated compiler writing
<tools?
In a word, no. lex is good for a lot of applications, but where maximum
performance is required, a hand-built scanner is necessary. It continually
surprises people that Zortech C compiles as fast as Turbo C, even though
ZTC is a 2 pass compiler and TC is 1 pass! The secret to speed is
in the scanner (not the symbol table!).
Other less significant reasons are:
1. When I started, in 1983, no lexes were available for MSDOS.
2. I don't care for copyright problems. I don't want to hire a lawyer
to interpret the licensing agreement.
3. The compiler has been occasionally ported to other platforms for
debugging purposes. Being constrained by the availability of a
particular version of lex is unacceptable.
4. It turns out that it's *very* useful to have complete control over
the compilation process from source code to EXE. Depending on
some other vendor's program which generates a critical section of
the compiler causes problems if the source to it is not available.
(See the cfront people with their problems with identifier length
in MSC!)
So-called 'compiler compilers' are also not terribly useful to me. They
are more appropriately called 'parser generators'. The parsing code itself
is a minor part of a real compiler. The 'compiler compiler' still requires
you to write symbol table, semantic analysis, optimization, and code
generation, which is over 95% of the compiler.
For programs where scanning and parsing are most of the job, like in
a tool like indent, lex and yacc are highly useful. Those tools are
also very nice for prototyping a new language, because it's easy to
drastically change the syntax of what you're compiling.
shankar@hpclscu.HP.COM (Shankar Unni) (03/02/90)
> I saw that comment about C++ not being LALR(1) in the g++ distribution, > and at the time believed it. However, my biggest thrill at OOPSLA '89 > was sitting at the same table as Bjarne Stroustrup for a few hours drinking > free beer. He said that he IS USING A LALR(1) GRAMMER for C++ 2.0. > He appeared sober & honest, therefore I assume that C++ is LALR(1), but > non-trivial. No, it becomes LALR(1) only by a trick: a feedback mechanism by which the lexer can: (a) consult a symbol table to see if an identifier is really a typedef name, and (b) an ambiguity resolver called by the parser to handle any remaining ambiguities. The whole thing is done by adding another layer between the lexer and the parser, with these smarts built in. Using the classical model of a table-driven scanner and parser, it is impossible to write a LALR(1) description for C++ (or for that matter, C). It could be LR(2), though; I can't be sure.. ---- Shankar Unni.
bs@alice.UUCP (Bjarne Stroustrup) (03/02/90)
Ron Guilmette (our resident C++ Entomologist) writes: > So the goal is good. What is *not* good is muddling the issue with meaningless > catch phrases like "C++ is not LALR(1)". In order to move the discussion onto > a higher plain, let's try to be accurate and just say that it would be nice > if an LALR(1) grammar for C++ could allow for much more disambiguation via > easy-to-implement LALR(1) syntax rules. > >What Bjarne probably meant (judging from the cfront 2.0 > >sources) is that he was using the LALR(1) parser generated by yacc to > >recognize C++. Exactly. Plus an oversmart ``lexical'' analyser. > Free advice: Second guessing Bjarne's intended meaning based on sketchy > second-hand accounts is probably inadvisable. Very nice advice. There can be no simple LALR(1) parser for C++. The reason is examples like: // let T be some type f() { T (*p)[7]; // declaration or expression? // declaration! T (*p)[7]->m = 7; // declaration or expression? // expression! } The rule is that anything that (syntactically) looks like a declaration is a declaration (this ensures C compatibility). What isn't might be an expression. This rule is simple, but requires a backtracking parser to cope with ``cute'' examples like the ones above. Had I had 20/20 foresight I would probably have chosen an LALR(1) grammar for C++. However, I did not (and still don't) consider syntax issues to be anywhere near as important as issues of type checking and access control so I underestimated people's desire/need for syntax based solutions.
ned@pebbles.cad.mcc.com (Ned Nowotny) (03/05/90)
In article <10541@alice.UUCP> bs@alice.UUCP (Bjarne Stroustrup) writes: >Had I had 20/20 foresight I would probably have chosen an LALR(1) grammar >for C++. However, I did not (and still don't) consider syntax issues to be >anywhere near as important as issues of type checking and access control >so I underestimated people's desire/need for syntax based solutions. Given the imprecise nature of the C++ specification, I am more than a little disappointed that the language does not have a grammar expressible in BNF form that will accept all legal strings and reject all illegal strings. (That, by the way, is what I consider to be the test of whether a given language is specifiable by a given grammar. While it may be true that some LALR(1) grammar will accept all legal C++ strings, the fact that the grammar must also accept illegal strings makes the claim that C++ is somehow a LALR(1) language something less than useful.) For example, when trying to resolve whether bugs in my code are the result of an incorrect understanding of the language on my part or a flaw in a given compiler, I would like to turn to an authoritative source to determine whether a given string I have written is even a legal construct. Unfortunately, the grammar given in the various reference manuals are not helpful precisely because they are not accompanied by a formal specification of the "smarts" built into the lexical analyzer. In fact, the specifications would not be as precise as a LALR(1) grammar in any case. The current (and, quite probably, permanent) situation is of little assistance to compiler writers and users of C++ alike. (For example, consider const friend functions: Everything I have read, including Lippman and the Release 2.0 Reference manual, SEEM to indicate that only member functions may be declared const functions. However, Keith Gorlen, for one, has declared friend functions to be const in his NIH Class Library code. This appears to be a reasonable thing to do. The grammar given in the 2.0 reference manual does not appear to disallow this, there is no semantic specification provided which disallows it, the Cfront 2.0 compiler which is the current reference implementation apparently accepts it, and it appears on its face to be a reasonable thing to do. A precise LALR(1) grammar would, at least, disambiguate the current legality of the construct while greater minds considered its usefulness and hazards.) Ned Nowotny, MCC CAD Program, Box 200195, Austin, TX 78720 Ph: (512) 338-3715 ARPA: ned@mcc.com UUCP: ...!cs.utexas.edu!milano!cadillac!ned ------------------------------------------------------------------------------- "We have ways to make you scream." - Intel advertisement in the June 1989 DDJ.
rfg@ics.uci.edu (Ronald Guilmette) (03/10/90)
In article <10541@alice.UUCP> bs@alice.UUCP (Bjarne Stroustrup) writes: >... There can be no simple LALR(1) parser for C++. Gosh darn it Bjarne! Here I am trying to dispel this inexact notion, and here you are perpetuating it! Of course in any *practical* sense, you are correct. Any real compiler or translator will probably try to use LALR(1) grammar rules to parse and disambiguate as much of that language as possible, but don't you agree that V* qualifies as an LALR(1) grammar and that this "grammar" accepts all valid sentences in C++? >Had I had 20/20 foresight I would probably have chosen an LALR(1) grammar >for C++. Don't you mean to say that you would have designed a language in which more cases could be determined to be either legal or illegal via a "simple" LALR(1) parse (without lexical tricks)? Isn't that more accurate? // Ron Guilmette (rfg@ics.uci.edu) // C++ Entomologist // Motto: If it sticks, force it. If it breaks, it needed replacing anyway.
rfg@ics.uci.edu (Ronald Guilmette) (03/10/90)
In article <6553@cadillac.CAD.MCC.COM> ned@MCC.COM (Ned Nowotny) writes: > >Given the imprecise nature of the C++ specification, I am more than a >little disappointed that the language does not have a grammar expressible >in BNF form that will accept all legal strings and reject all illegal >strings. As Joe English also points out, this is utter nonsense. In all of the useful languages that I know of, the correctness of statements is based upon both syntax *and* semantics. Neither one can be used in isolation to decide on the correctness of statements. >... While it may be >true that some LALR(1) grammar will accept all legal C++ strings, the fact >that the grammar must also accept illegal strings makes the claim that >C++ is somehow a LALR(1) language something less than useful. I agree that in practice, nobody actually is stupid enough to use V* as their LALR(1) grammar for parsing C++ or other languages, but just because the statement "C++ is LALR(1)" may not be "useful" does not mean that it is not 100% accurate. In fact, I believe that it is. // Ron Guilmette (rfg@ics.uci.edu) // C++ Entomologist // Motto: If it sticks, force it. If it breaks, it needed replacing anyway.
sakkinen@tukki.jyu.fi (Markku Sakkinen) (03/14/90)
In article <25F8C92A.9349@paris.ics.uci.edu> rfg@ics.uci.edu (Ronald Guilmette) writes: >In article <6553@cadillac.CAD.MCC.COM> ned@MCC.COM (Ned Nowotny) writes: >> >>Given the imprecise nature of the C++ specification, I am more than a >>little disappointed that the language does not have a grammar expressible >>in BNF form that will accept all legal strings and reject all illegal >>strings. > >As Joe English also points out, this is utter nonsense. [...] >>... While it may be >>true that some LALR(1) grammar will accept all legal C++ strings, the fact >>that the grammar must also accept illegal strings makes the claim that >>C++ is somehow a LALR(1) language something less than useful. > >I agree that in practice, nobody actually is stupid enough to use V* as their >LALR(1) grammar for parsing C++ or other languages, but just because the >statement "C++ is LALR(1)" may not be "useful" does not mean that it is >not 100% accurate. In fact, I believe that it is. Sorry, Mr. Guilmette, I think it is _you_ who are repeating the same utter nonsense too many times in this group. Please stand back for a while and reflect on how vacuous any grammatical classification of languages becomes is one takes your attitude. Alternatively, go post your opinion to the comp.theory group (or comp.compilers) and get your knuckles rapped on by real experts. Otherwise, you seem to be one of the most prolific and useful contributors in this group. Markku Sakkinen Department of Computer Science University of Jyvaskyla (a's with umlauts) Seminaarinkatu 15 SF-40100 Jyvaskyla (umlauts again) Finland SAKKINEN@FINJYU.bitnet (alternative network address)
rfg@ics.uci.edu (Ronald Guilmette) (03/21/90)
In article <3742@tukki.jyu.fi> sakkinen@jytko.jyu.fi (Markku Sakkinen) writes: >In article <25F8C92A.9349@paris.ics.uci.edu> rfg@ics.uci.edu (Ronald Guilmette) writes: >>In article <6553@cadillac.CAD.MCC.COM> ned@MCC.COM (Ned Nowotny) writes: >>> >>>Given the imprecise nature of the C++ specification, I am more than a >>>little disappointed that the language does not have a grammar expressible >>>in BNF form that will accept all legal strings and reject all illegal >>>strings. >> >>As Joe English also points out, this is utter nonsense. [...] >>>... While it may be >>>true that some LALR(1) grammar will accept all legal C++ strings, the fact >>>that the grammar must also accept illegal strings makes the claim that >>>C++ is somehow a LALR(1) language something less than useful. >> >>I agree that in practice, nobody actually is stupid enough to use V* as their >>LALR(1) grammar for parsing C++ or other languages, but just because the >>statement "C++ is LALR(1)" may not be "useful" does not mean that it is >>not 100% accurate. In fact, I believe that it is. > >Sorry, Mr. Guilmette, I think it is _you_ who are repeating the same >utter nonsense too many times in this group. Please stand back for >a while and reflect on how vacuous any grammatical classification >of languages becomes is one takes your attitude. Alternatively, >go post your opinion to the comp.theory group (or comp.compilers) >and get your knuckles rapped on by real experts. I believe that I failed to make my point clearly enough. I used the (admitedly extreme) example of V* as a grammar for C++ just to make it quite evident that a C++ grammar could be LALR(1). I only did this for the sake of argument. As should be demonstrated by Jim Roskind's grammar, you need not devolve the grammar all the way down to V* to get it to be LALR(1). Quite the contrary. If you are willing to do just a few more things with semantic analysis rather than syntax analysis (relative to what current C++ implementors seem to be doing) then you can in fact have a useful and practical LALR(1) grammar for C++. That was my point. I just stated it badly. // Ron Guilmette (rfg@ics.uci.edu) // C++ Entomologist // Motto: If it sticks, force it. If it breaks, it needed replacing anyway.
pcg@odin.cs.aber.ac.uk (Piercarlo Grandi) (03/23/90)
In article <26073795.10139@paris.ics.uci.edu> rfg@ics.uci.edu (Ronald Guilmette) writes: If you are willing to do just a few more things with semantic analysis rather than syntax analysis (relative to what current C++ implementors seem to be doing) then you can in fact have a useful and practical LALR(1) grammar for C++. That was my point. I just stated it badly. Sorry Ron, but we really still disagree on a question of terminology here; a LALR(1) grammar belongs to the context free class. If you need semantic information to parse C++ (and by all means you need it) then your intelligent lexer is also a translator from a context sensitive C++ to another language that is indeed LALR(1), BUT IS NO LONGER C++. In particular this language has typedef names as tokens/keywords for the scopes to which they apply, as in a sense when you define a class name in C++ you are creating a new scoped reserved word, the class name, and certain phrases can only be parsed if you know that the given string is such a token. Your point is that you can 'have a useful and practical LALR(1) PARSER for A C++ COMPILER'; such a *parser* however does not parse C++ itself, but a C++ derivative, generated by the intelligent lexer. C++ itself does not admit a context free *grammar*, much less a LALR(1) one. I could say that C++ is a *family* of LALR(1) languages, each of which differs from the others by a different set of typedef names in different scopes, and an intelligent lexer filters out the particular language belonging to this family and passes it to the LALR(1) parser. Typedef names do not turn Classic C itself into a context sensitive language by the slimmest of margins. Incidentally, you can easily see that the requirement for a leading 'struct' or 'enum' or 'union' before a tag in a declaration was designed to help the parser be LL(1). Too bad that 'typedef' was later introduced as a *storage class* and not as new type of tag, e.g. not something like 'mode <name> { <abstract declarator> } ....', which could be likened to a one field struct. In C the problem does not occur because you can distinguish declarations that include a typedef name from a statement in a context free way because you need a '=' in an initialization and you cannot intermix declarations with statements. The '=' for initialization is particularly crucial; it used to be that Classic C did not require it (as in 'int i 3;'), but it was introduced later on because, as Ritchie put it, certain things looked so much like procedure declarations that the parser got confused (as in 'int j 1; int k (j)'). Stroustrup has reintroduced the old bugaboo. Those that do not know history... :-). Note that this aspect of C++, that implies dynamic augmentation of the set of keywords for a given scope, is strongly reminiscent of Algol 68, and its (in)famous ambiguity between mode and operator denotations, and I think that Stroustrup was more familiar with the fine details of Algol 68 than of C at some point in his life. In particular, while C++ surely does not admit a context free LALR(1) grammar, it does admit description with a two level grammar (which is context sensitive), Algol 68 style, and the second level grammar can well be LALR(1) (those that do know two level grammars please excuse the poetic license here :->). -- Piercarlo "Peter" Grandi | ARPA: pcg%cs.aber.ac.uk@nsfnet-relay.ac.uk Dept of CS, UCW Aberystwyth | UUCP: ...!mcvax!ukc!aber-cs!pcg Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk
rfg@ics.uci.edu (Ronald Guilmette) (03/24/90)
In article <PCG.90Mar23120003@odin.cs.aber.ac.uk> pcg@odin.cs.aber.ac.uk (Piercarlo Grandi) writes: > >In article <26073795.10139@paris.ics.uci.edu> rfg@ics.uci.edu (Ronald >Guilmette) writes: > > If you are willing to do just a few more things with semantic analysis > rather than syntax analysis (relative to what current C++ implementors > seem to be doing) then you can in fact have a useful and practical LALR(1) > grammar for C++. That was my point. I just stated it badly. > >Sorry Ron, but we really still disagree on a question of terminology >here; a LALR(1) grammar belongs to the context free class. If you need >semantic information to parse C++ (and by all means you need it) then >your intelligent lexer is also a translator from a context sensitive >C++ to another language that is indeed LALR(1), BUT IS NO LONGER C++. > >In particular this language has typedef names as tokens/keywords for the That (I claim) is a design decision on the part of the implementor. (And we are now getting down to the meat of my point.) I fully admit that C and C++ are easier to "compile" if you have separate token types for "identifier" and for "type name", but is this absolutely manditory? I think not. Without having such distinctions made at the lexical level (or the basis of feedback from semantic analysis), you will of course end up with excessively general non-terminals like (for instance): declarative_or_executable_statement: whose corresponding rules will allow stuff like: F ( Y ) = Z; even in cases where (semantically) the context demands that F be treated as the name of a function, but (as I said before) that just means that you gotta do more work in the semantic analysis to properly detect and flag such errors. (Footnote: Actually, that may be a bad example, because I think that even if "F" is the name of a function, the above statement may be legal, e.g. in cases where F returns a reference.) // Ron Guilmette (rfg@ics.uci.edu) // C++ Entomologist // Motto: If it sticks, force it. If it breaks, it needed replacing anyway.
pcg@rupert.cs.aber.ac.uk (Piercarlo Grandi) (03/28/90)
In article <260A9B1D.17399@paris.ics.uci.edu> rfg@ics.uci.edu (Ronald Guilmette) writes: I fully admit that C and C++ are easier to "compile" if you have separate token types for "identifier" and for "type name", but is this absolutely manditory? I think not. Without having such distinctions made at the lexical level (or the basis of feedback from semantic analysis), you will of course end up with excessively general non-terminals like (for instance): declarative_or_executable_statement: But this is the meat of _my_ argument: this is no longer a grammar for C++, it is a grammar for a family of languages of which C++ is a member, and you use semantic (context dependent) rules to translate/disambiguate it to a C++ grammar. This is a fine implementation technique; you parse a more general language, and rely on non-grammar rules to narrow it down. Whether the *language* admits a context free, LALR(1) grammar (it does not) is one issue, whether the *compiler* can make use of a LALR(1) parser generator plus semantic analysis (it can) is an issue of how to engineer a parser for a non context free language using a mixed bag of tools. Essentially, using a LALR(1) parser generator aided by semantic analysis is hand crafting an attribute grammar parser. -- Piercarlo "Peter" Grandi | ARPA: pcg%cs.aber.ac.uk@nsfnet-relay.ac.uk Dept of CS, UCW Aberystwyth | UUCP: ...!mcvax!ukc!aber-cs!pcg Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk