Re: Designing Lisp from scratch

[email protected] Fri, 23 Mar 2007 03:38:09 EDT
Newsgroups gmane.comp.lang.lightweight
Message-ID <[email protected]>
 
 
 
I fully agree with you that jamming the lexing, parsing, and other code all  
into one large mess of a file is less desirable than separating them the way  
it's done with Lex / Yacc.  But uCalc doesn't do it that way either.
 
Lex / Yacc has been the established way of doing things, and there are many  
tools that build on it, either by trying to simplify it, expand it, or emulate 
 it on other platforms.  Naturally, you will want explanations of how uCalc  
does this as well.  The best way to try to understand how uCalc improves on  
Lex / Yacc, however, is to try not to.  That is because the approaches are  
different enough that there isn't a very direct way to correlate the two.   This 
does not imply that one approach is necessarily better than the other, but  
just different.  Just like a bus and a train serve a generally similar  purpose, 
but achieve the goal in quite different ways.
 
That said let me see if I can try to explain my approach a little  better.  
Without using Lex / Yacc as a reference point, think of system  that uses 
regular expressions to process a stream of characters, but not for the  purpose of 
producing tokens, and it also applies grammar rules to an input  stream, but 
doesn't generate a parser.  The process of matching patterns  based on regular 
expressions as well as the process of applying grammar rules  are applied to 
the very same input stream, though it is not done one after the  other.  
Instead, both are in fact the very same process.  Think of it  as a kind of lexer; 
but one that doesn't just match regular expression  patterns.   It matches 
whole syntactical patterns, which may consist  of a combination of regular 
expressions and terminal & non-terminal-like  entities, though it's not really a 
grammar in the BNF form.
 
You might wonder how a parser can automatically be generated for something  
like this.  But one isn't.  There is a built-in uCalc parser.   And it can only 
parse uCalc code.  When a syntax pattern finds a match, the  code is reduced 
to a simpler syntax (based on your definitions) until it reduces  to the kind 
of code that uCalc's parser knows how to parse.  You need not  know what the 
lowest level of code it reduces to looks like.  You can  reduce a language to 
an intermediate language.

Theoretically, you  can rewrite and reduce the source code of any kind of 
language until it is  binary code (not that you'd want to).  You can also do the 
same down to  assembly; though that would still be pretty complicated.  You 
can also  reduce code down to C code.  That's what you do with Lex / Yacc.  Why  
would you want to try any another way?  Several reasons:  
 
1.  C is not a language that is specifically designed for language  
construction, even if it can be used for that.  The C parsing code is of  course 
significantly simpler than equivalent assembly code, which in turn is  simpler than 
binary.  But in the same way, the special uCalc bootstrap  language, which is 
very specifically designed for language building and nothing  else, is 
designed to be even simpler to deal with than C parser code.   When I say simpler, I 
mean you end up with much less code, with all of it more  closely matching the 
intent of what you are trying to do.  Just the same  that C's version of 
hello world:
 
printf("hello, world!");
 
takes less code, all of which more closely conveys intent than the  
equivalent x86 DOS assembler code:
 
db msg 'Hello, world!$'
mov ah, 09h
lea dx, msg ; or mov dx, offset  msg
int 21h
mov ax,4C00h
int 21h
 
So too, uCalc language construction code would typically be considerably  
less in volume, with more of the code directly related to conveying intent than  
code used and produced by Lex / Yacc.
 
2.  Grammar for languages like Scheme might use symbols that are  invalid in 
C, thus causing it not to work with Yacc (conventional C  implementations of 
it).  I'm not 100 percent sure of this.  However,  in an earlier message I 
asked if anyone could supply Lex / Yacc code for Lisp,  and I've also searched on 
my own, and still haven't found any.  In my  search, I have found hints that 
people will not, cannot, need not, or would  simply prefer not to do a 
conventional C-based Lex / Yacc implementation of  Scheme or other Lisp.  I would be 
interested in more of a definitive answer  on whether it can be done or if it 
is too hard to do, or whether creating a Lisp  parser by hand is too easy for 
one to bother with Lex / Yacc.
 
There is of course no difficulty or complication in implementing Lisp in  
uCalc.  Code is not reduced to C, but to the uCalc language, which can  handle 
any kind of symbol.
 
3.  If a language has a mutable or extendible syntax (or semantics),  then 
you can forget about using Lex / Yacc .  Once the syntax is frozen  you'd limit 
the language's ability to let programmers add new syntax.  I've  seen 
something like this said in reference to languages like Forth, Tcl and  more.  Again, 
I'd like to be corrected on this one if I'm wrong.
 
Either way, there's no problem regarding extendible syntax in  uCalc.
 
4.  I've seen it said that grammars for some languages (like Perl)  simply 
cannot be expressed effectively in BNF form.  Though I haven't  tackled Perl 
yet, uCalc does not deal with BNF grammars.  I don't foresee  any obstacles to 
reducing Perl-like syntax like I've done for other  languages.
 

I gave an analogy of bus vs train.  Though from my personal biased  
perspective I think of Lex / Yacc like a bus and uCalc more like a car.   The bus will 
get you to anywhere around the city.  Though typically you  might have to 
change buses one or two times.  And then once it drops you  off, you may have to 
walk a couple of blocks to reach your actual  destination.  Also, once the 
itinerary of the bus is already set, you can't  add to it along the way.
 
Daniel  Corbier
uCalc Language Builder
www.ucalc.com

 
In a message dated 3/20/07 5:33:04 AM Eastern Standard Time,  
[email protected] writes:

Conversely, with lex and yacc, the system would be much more modular.  
Instead of having lexing, parsing, and the rest all thrown together in  
one big mess, you have the various levels cleanly separated. Once it's  
tokenized, you don't care about characters anymore. Once it's parsed,  
you don't care about syntax at all anymore, and deal only with  
semantics. I'm just trying to point out that there is something to be  
said for both  approaches.

Regards,

Bob






************************************** AOL now offers free email to everyone. 
 Find out more about what's free from AOL at http://www.aol.com.