Compiler/Preprocessor: Difference between revisions
Content added Content deleted
(→Task) |
(→{{header|Wren}}: Modified to allow up to 3 command line arguments as per revised task description.) |
||
Line 260: | Line 260: | ||
A fairly naive solution compared to the complexities of a modern C pre-processor. |
A fairly naive solution compared to the complexities of a modern C pre-processor. |
||
I've made the simplifying assumption that macro parameters in a macro definition will always be separated from other tokens by at least one space. |
|||
I've made the following simplifying assumptions: |
|||
I've also assumed that the header files will always be actual files, and never entered from the console. |
|||
⚫ | |||
2. Macros will not occur in string literals, nor closing parentheses within macro argument strings. |
|||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
⚫ | |||
import "./str" for Char |
import "./str" for Char |
||
import "./pattern" for Pattern |
import "./pattern" for Pattern |
||
Line 282: | Line 280: | ||
var clargs = Process.arguments |
var clargs = Process.arguments |
||
if (clargs.count |
if (clargs.count > 3) { |
||
System.print(" |
System.print("There can't be more than 3 command line arguments: |
||
-d // debug mode, comments will be included in output |
|||
input // filename: if absent or == console, gets input from console |
|||
output // filename: if absent or == console, sends output to console") |
|||
return |
return |
||
} |
} |
||
var debug = clargs.contains("-d") || clargs.contains("--debug") |
|||
var fileName = clargs[0] |
|||
if (debug) { |
|||
clargs.remove("-d") |
|||
clargs.remove("--debug") |
|||
} |
|||
var inputFileName = "console" |
|||
if (clargs.count > 0) inputFileName = clargs[0] |
|||
var lines |
|||
if (inputFileName != "console") { |
|||
⚫ | |||
⚫ | |||
var n = Input.integer("How many lines are to be entered? : ", 1) |
|||
System.print("\nOK, enter the lines and press enter after each one.\n") |
|||
lines = List.filled(n, null) |
|||
for (i in 0...n) lines[i] = Input.text("") |
|||
⚫ | |||
} |
|||
var macros = [] |
var macros = [] |
||
var comments = [] |
var comments = [] |
||
var used = [] |
var used = [] |
||
var includes = Stack.new() |
var includes = Stack.new() |
||
⚫ | |||
var i = 0 |
var i = 0 |
||
while (i < lines.count) { |
while (i < lines.count) { |
||
Line 307: | Line 324: | ||
} else { |
} else { |
||
includes.push([fname, i + lines2.count - 1]) |
includes.push([fname, i + lines2.count - 1]) |
||
comments.add("/* Include Header %(fname) */") |
if (debug) comments.add("/* Include Header %(fname) */") |
||
} |
} |
||
lines = lines[0...i] + lines2 + lines[i+1..-1] |
lines = lines[0...i] + lines2 + lines[i+1..-1] |
||
Line 345: | Line 362: | ||
var defn = line[j..-1].trimStart() |
var defn = line[j..-1].trimStart() |
||
macros.add([name, params, defn]) |
macros.add([name, params, defn]) |
||
if ( |
if (debug) { |
||
if (params == null) { |
|||
⚫ | |||
⚫ | |||
} else { |
|||
⚫ | |||
comments.add("/* Define %(name)(%(params.toString[1...-1])) as %(defn) */") |
|||
} |
|||
} |
} |
||
lines.removeAt(i) |
lines.removeAt(i) |
||
Line 354: | Line 373: | ||
Fiber.abort("Unknown directive.") |
Fiber.abort("Unknown directive.") |
||
} |
} |
||
if (debug) { |
|||
while (includes.count > 0 && i >= includes.peek()[1]) { |
|||
while (includes.count > 0 && i >= includes.peek()[1]) { |
|||
comments.add("/* End %(includes.pop()[0]) */") |
|||
} |
|||
} |
} |
||
} |
} |
||
Line 394: | Line 415: | ||
} |
} |
||
} |
} |
||
if (debug) { |
|||
while (includes.count > 0) { |
|||
while (includes.count > 0) { |
|||
comments.add("/* End %(includes.pop()[0]) */") |
|||
} |
|||
} |
} |
||
used = Lst.distinct(used) |
used = Lst.distinct(used) |
||
if (used.count > 0) { |
if (used.count > 0) { |
||
var temp = (used.count == 1) ? used[0] : used[0..-2].join(", ") + " and " + used[-1] |
var temp = (used.count == 1) ? used[0] : used[0..-2].join(", ") + " and " + used[-1] |
||
comments.add("/* Used %(temp) */") |
if (debug) comments.add("/* Used %(temp) */") |
||
} |
} |
||
comments = comments.join("\n") |
if (debug) comments = comments.join("\n") |
||
var outputFileName = "console" |
|||
// write to terminal |
|||
if (clargs.count > 1) outputFileName = clargs[1] |
|||
System.print(comments) |
|||
⚫ | |||
if (outputFileName == "console") { |
|||
// write to a file |
|||
⚫ | |||
⚫ | |||
if (debug) System.print(comments) |
|||
System.print(src) |
|||
} else { |
|||
⚫ | |||
⚫ | |||
⚫ | |||
if (debug) { |
|||
file.writeBytes(comments) |
|||
file.writeBytes("\n") |
|||
} |
|||
⚫ | |||
⚫ | |||
} |
|||
}</lang> |
}</lang> |
||
Line 419: | Line 448: | ||
Using the example files; |
Using the example files; |
||
<pre> |
<pre> |
||
$ wren-cli compiler_preprocessor.wren -d |
|||
How many lines are to be entered? : 4 |
|||
OK, enter the lines and press enter after each one. |
|||
#include "Header.h" |
|||
#define width 5 |
|||
#define height 6 |
|||
area = #area(height, width)#; |
|||
Output: |
|||
/* Include Header "Header.h" */ |
/* Include Header "Header.h" */ |
||
/* Define area(h, w]) as h * w */ |
/* Define area(h, w]) as h * w */ |
||
Line 447: | Line 488: | ||
{{out}} |
{{out}} |
||
<pre> |
<pre> |
||
$ wren-cli compiler_preprocessor.wren -d Source.t |
|||
Output: |
|||
/* Include Header "Header.h" */ |
/* Include Header "Header.h" */ |
||
/* Define area(h, w) as h * w */ |
/* Define area(h, w) as h * w */ |