Compiler/Preprocessor: Difference between revisions

Content added Content deleted
(→‎{{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:


1. Macro parameters in a macro definition will always be separated from other tokens by at least one space.
I've also assumed that the header files will always be actual files, and never entered from the console.


Note that the program errors out if there are any syntax or other errors when defining the macros.
2. Macros will not occur in string literals, nor closing parentheses within macro argument strings.
<lang ecmascript>import "os" for Process

import "./ioutil" for FileUtil, File, Input
Note that if macros are used incorrectly, there are no errors or warnings. The program simply assumes that this is what was intended. However, the program errors out if there are any syntax or other errors when defining the macros.
<lang ecmascript>import "os" for Process
import "./ioutil" for FileUtil, File
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 != 1) {
if (clargs.count > 3) {
System.print("Please pass exactly one command line argument, the file name to preprocess.")
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") {
lines = FileUtil.readLines(inputFileName)
} else {
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("")
System.print()
}

var macros = []
var macros = []
var comments = []
var comments = []
var used = []
var used = []
var includes = Stack.new()
var includes = Stack.new()
var lines = FileUtil.readLines(fileName)
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 (params == null) {
if (debug) {
comments.add("/* Define %(name) as %(defn) */")
if (params == null) {
comments.add("/* Define %(name) as %(defn) */")
} else {
} else {
comments.add("/* Define %(name)(%(params.toString[1...-1])) as %(defn) */")
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]) {
comments.add("/* End %(includes.pop()[0]) */")
while (includes.count > 0 && i >= includes.peek()[1]) {
comments.add("/* End %(includes.pop()[0]) */")
}
}
}
}
}
Line 394: Line 415:
}
}
}
}
if (debug) {
while (includes.count > 0) {
comments.add("/* End %(includes.pop()[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)
System.print(src)


if (outputFileName == "console") {
// write to a file
System.print("Output:\n")
File.create("output_from_" + fileName) { |file|
file.writeBytes(comments)
if (debug) System.print(comments)
file.writeBytes("\n")
System.print(src)
} else {
file.writeBytes(src)
File.create(outputFileName) { |file|
file.writeBytes("\n")
if (debug) {
file.writeBytes(comments)
file.writeBytes("\n")
}
file.writeBytes(src)
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 */