Path: csiph.com!weretis.net!feeder6.news.weretis.net!feeder.usenetexpress.com!feeder1.iad1.usenetexpress.com!border1.nntp.dca1.giganews.com!border2.nntp.dca1.giganews.com!nntp.giganews.com!news.iecc.com!.POSTED.news.iecc.com!nerds-end From: Hans-Peter Diettrich Newsgroups: comp.compilers Subject: Re: Designing a Domain-specific language Date: Wed, 24 May 2017 06:42:15 +0200 Organization: Compilers Central Lines: 39 Sender: news@iecc.com Approved: comp.compilers@iecc.com Message-ID: <17-05-009@comp.compilers> References: <17-05-007@comp.compilers> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Injection-Info: miucha.iecc.com; posting-host="news.iecc.com:2001:470:1f07:1126:0:676f:7373:6970"; logging-data="63183"; mail-complaints-to="abuse@iecc.com" Keywords: design Posted-Date: 25 May 2017 10:58:42 EDT X-submission-address: compilers@iecc.com X-moderator-address: compilers-request@iecc.com X-FAQ-and-archives: http://compilers.iecc.com Xref: csiph.com comp.compilers:1876 Am 23.05.2017 um 16:12 schrieb dror.openu@gmail.com: > My dilemma is: "How's the compile process should be when you have many files". I thought about this process for the second requirement, and I'd like to hear your opinion: > 1. scan all the files (assume we have k files). > 2. for each of the files: > 2.1 run the lexer together with parser and build a parse tree. > 3. now, I have k parse trees (but only one entry-point/main). > 4. if there's a circular dependencies return an error > 5. resolve the "include"s by merging the trees into one tree. John already pointed out two commonly used methods, so let me only add some keys. A *preprocessor* can be implemented as a stand-alone tool, that resolves the "include ..." directives, and produces a combined output file that then can be compiled. Or it does the same as kind of a filter, sitting between the lexer and parser, so that it can feed one sequential stream of tokens to the parser. The preprocessor either switches its input amongst files, in order to produce a combined file, or it switches amongst lexers, each of which processes a single input file. A *linker* resolves references between object modules, or AST's, so that the result is either a single object or executable file, or a single combined AST (parse tree). A clever linker can cache individual definitions (variables, functions...), and load only the really required definitions on demand. This technique allows to eliminate all unused parts of the source files from the final program. Again a linker can be implemented as a stand-alone tool, or as part of a compiler. Caveat: If your "include" directive allows to insert *incomplete* definitions, e.g. individual lines of code into a function, only a preprocessor can produce valid input for the parser. Otherwise, if all definitions can be parsed without occurences of embedded "include" directives, all definitions (of identifiers) can be parsed individually, and merged into a common list of definitions, as the top level of the parse tree, or as a list of individual parse trees for each listed definition. DoDi