Jump to content

Compiler/Simple file inclusion pre processor: Difference between revisions

m
syntax highlighting fixup automation
(Specified the minimum functionality required for the pre-processor.)
m (syntax highlighting fixup automation)
Line 75:
When run, the pre-processor will read source from standard input and write the resultant source to standard output. If standard output is re-directed to a temporary source file, it can then be compiled/interpreted with the actual Algol 68 compiler.
<br>(NB: The source must end with a line-feed)
<langsyntaxhighlight lang="algol68"># Algol 68 pre-processor #
# Processes read/include pragmas in an Algol 68 upper stropping source #
# It is assumed _ is allowd in tags and bold words #
Line 449:
FI
 
END</langsyntaxhighlight>
{{out}}
Pre-processing the following program:
Line 482:
<br>It differs from GAWK syntax in that the include directive can appear inside or outside functions. The file name can be quoted or not. Nested includes are not supported.
<br>The source can be a named file or read from stdin. If it is read from stdin, <code>-v sec=sourceName</code> can be specified on the AWK command line to name the file. The pre-processed source is writen to stdout.
<langsyntaxhighlight lang="awk"># include.awk: simple file inclusion pre-processor
#
# the command line can specify:
Line 534:
printf( "#line %d %s\n", NR, ( srcName != "" ? srcName : FILENAME ) );
 
} # includeFile</langsyntaxhighlight>
 
=={{header|J}}==
Line 544:
This approach is not recursive (and while it seems to offer little advantage over the native implementation of 'load', it does support 'load' inside multi-line string constants, as long as the reference(s) to the content being loaded would be supportable as a J script reference).
 
<langsyntaxhighlight Jlang="j">preproc=: {{
lines=. <;.2 LF,~CR-.~fread y
for_ndx. |.I.'load'-:"1 (4&{.@>) lines do.
Line 555:
end.
0!:0;lines
}}</langsyntaxhighlight>
 
=={{header|Julia}}==
Line 565:
the standard Julia syntax. Calls to the <code>include</code> function that contain a single argument which is a string in parentheses will be preproccessed. Other calls to <code>include</code> with different arguments will not be preprocessed by <code>preprocess.jl</code>.
 
<langsyntaxhighlight lang="julia"># preprocess.jl convert includes to file contenets
 
infile = length(ARGS) > 0 ? ARGS[1] : stdin
Line 583:
output = replace(input, r"\sinclude\(\"[^\"]+\"\)\s" => includefile)
write(outfile, output)
</syntaxhighlight>
</lang>
 
=={{header|Phix}}==
Standard feature. Phix ships with a bunch of standard files in a builtins directory, most of which it knows how to "autoinclude", but some must be explicitly included ([http://phix.x10.mx/docs/html/include.htm full docs]). You can explicitly specify the builtins directory or not (obviously without it will look in the project directory first), and use the same mechanism for files you have written yourself. There is no limit to the number or depth of files than can be included. Relative directories are honoured, so if you specify a (partial) directory that is where it will look first for any sub-includes. You can also use single line "stub includes" to redirect include statements to different directories/versions. Note that namespaces are '''not''' supported by pwa/p2js. You can optionally use double quotes, but may then need to escape backslashes. Includes occur at compile time, as opposed to dynamically.
<!--<langsyntaxhighlight Phixlang="phix">-->
<span style="color: #008080;">include</span> <span style="color: #000000;">builtins</span><span style="color: #0000FF;">/</span><span style="color: #004080;">complex</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span>
<span style="color: #008080;">include</span> <span style="color: #004080;">complex</span><span style="color: #0000FF;">.</span><span style="color: #000000;">e</span> <span style="color: #000080;font-style:italic;">-- also valid</span>
<span style="color: #008080;">include</span> <span style="color: #008000;">"builtins\\complex.e"</span> <span style="color: #000080;font-style:italic;">-- ditto</span>
<!--</langsyntaxhighlight>-->
If the compiler detects that some file has already been included it does not do it again (from the same directory, two or more files of the same name ''can'' be included from different directories).
I should perhaps also state that include handling is part of normal compilation/interpretation, as opposed to a separate "preprocessing" step, and that each file is granted a new private scope, and while of course there is only one "global" scope, it will use the implicit include hierarchy to automatically resolve any clashes that might arise to the most appropriate one, aka "if it works standalone it should work exactly the same when included in as part of a larger application".
Line 597:
And so on to the task as specified: Since the task specifies it "is about implementing a pre-processor for ''your language'', not just describing it's features" and as per discussions on the talk page, and the above, a "preprocessor" for Phix would fail in so many ways it is simply not really worth attempting, and should certainly never actually be used.<br>
The following will replace include statements with file contents, but do '''not''' expect it to work or do anything useful on any existing [Phix] code. Mutually recursive includes will cause a mutually recursive infinite loop, until you run out of memory, that is without adding some kind of "already done" stack to the following.
<!--<langsyntaxhighlight Phixlang="phix">-->
<span style="color: #008080;">function</span> <span style="color: #000000;">preprocess</span><span style="color: #0000FF;">(</span><span style="color: #004080;">string</span> <span style="color: #000000;">filename</span><span style="color: #0000FF;">)</span>
<span style="color: #004080;">sequence</span> <span style="color: #000000;">inlines</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">get_text</span><span style="color: #0000FF;">(</span><span style="color: #000000;">filename</span><span style="color: #0000FF;">,</span><span style="color: #004600;">GT_LF_STRIPPED</span><span style="color: #0000FF;">),</span>
Line 612:
<span style="color: #008080;">return</span> <span style="color: #000000;">outlines</span>
<span style="color: #008080;">end</span> <span style="color: #008080;">function</span>
<!--</langsyntaxhighlight>-->
As the Wren entry eloquently puts it: The above code is limited in the sense that all top-level variables of the imported module (not just the specifically "global" ones) are now visible in the outer scope. Consequently, the code will no longer compile if there are any name clashes.
 
Line 632:
 
A Raku script to do source filtering / preprocessing: save it and call it 'include'
<syntaxhighlight lang="raku" perl6line>unit sub MAIN ($file-name);
my $file = slurp $file-name;
put $file.=subst(/[^^|['{{' \s*]] '#include' \s+ (\S+) \s* '}}'?/, {run(«$*EXECUTABLE-NAME $*PROGRAM-NAME $0», :out).out.slurp(:close).trim}, :g);</langsyntaxhighlight>
 
This will find: any line starting with '#include' followed by a (absolute or relative) path to a file, or #include ./path/to/file.name enclosed in double curly brackets anywhere in the file.
Line 643:
 
Top level named... whatever, let's call it 'preprocess.raku'
<syntaxhighlight lang="raku" perl6line># Top level test script file for #include Rosettacode
# 'Compiler/Simple file inclusion pre processor' task
 
Line 651:
 
#include ./include1.file
</syntaxhighlight>
</lang>
 
include1.file
Line 740:
 
Nevertheless, it is possible to write a limited pre-processor in Wren (the VM itself is written in C):
<langsyntaxhighlight lang="ecmascript">import "io" for File
 
var source = File.read("source.wren")
Line 764:
}
 
File.create("source2.wren") { |file| file.writeBytes(source) }</langsyntaxhighlight>
<br>
The above code is limited in the sense that '''all''' top-level variables of the imported module (not just the specifically imported ones) are now visible in the outer scope. Consequently, the code will no longer compile if there are any name clashes.
 
The obvious solution of placing the imported code in a block and then 'lifting' the specifically imported variables into the outer scope does not work because of Wren's rather strange scoping rules. If you did this, then the imported module's top level variables would no longer be top-level relative to the code as a whole and hence would no longer be visible to classes defined within the module itself! For example, if you try to run the following script, you get the error shown:
<langsyntaxhighlight lang="ecmascript">var B
 
{ // block starts here
Line 783:
} // end of block
 
B.method()</langsyntaxhighlight>
 
Other problems include dealing with '''import''' statements which have been commented out (not catered for in the above pre-processor) and resolving import file paths which is not actually set in stone but depends on how Wren is being embedded. The above pre-processor code only deals with paths which are relative to the current directory.
10,333

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.