Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Include, define, and undef preproc directives all work now. Also, now…

… using packrat parsing -- much much faster.
  • Loading branch information...
commit 55f789ef10415f04f40d3e7f393433d86b632f9d 1 parent dc91f11
@speveril authored
View
3  inc.vc
@@ -0,0 +1,3 @@
+int add(int a, int b) {
+ return a + b;
+}
View
19 src/lib/vergec/compiler.lua
@@ -35,17 +35,14 @@ function VergeC.search(this, nodetype, start)
end
function VergeC.compile(this)
- print("COMPILE STEP")
+ if not VergeC.scope then
+ VergeC.scope = { {} }
+ end
- this.scope = { {} } -- scope[1] is global scope, which we always have
+ this.scope = VergeC.scope
this.ast = this:cleanNode(this.ast)
this:compileNode(this.ast)
-
- print("TYPEDEFS")
- for k,v in pairs(VergeC.typedefs) do
- print(" " .. k)
- end
end
function VergeC.findVarInScope(this, varname)
@@ -83,7 +80,7 @@ function VergeC.compileNode(this, node)
local scope = #this.scope
if this.scope[scope][node[2]] then
- VergeC.error("COMPILE ERROR\n Redeclaration of variable '" .. node.name .. "'", node.index)
+ this:error("COMPILE ERROR\n Redeclaration of variable '" .. node.name .. "'", node.index)
else
if name[2] == 'globalvar' then this:emit("VergeC.bin.") elseif name[2] == 'membervar' then this:emit("") else this:emit("local ") end
this:emit(node[2].value .. " = ")
@@ -94,7 +91,7 @@ function VergeC.compileNode(this, node)
if VergeC.typedefs[node[1].value] then
scopeentry = { type = node[1].value, ident = node[2].value }
else
- VergeC.error("COMPILE ERROR\n Unknown type '" .. node[1].value .. "' in declaration.")
+ this:error("COMPILE ERROR\n Unknown type '" .. node[1].value .. "' in declaration.", node.index)
end
else
scopeentry = { type = node[1].token_type, ident = node[2].value }
@@ -145,6 +142,8 @@ function VergeC.compileNode(this, node)
-- create new scope level
local localscope = {}
local params = {}
+
+ table.insert(this.scope[1], { type = node[1].value, ident = node[2].value })
table.insert(this.scope, localscope)
-- build function head and signature
@@ -385,7 +384,7 @@ function VergeC.compileNode(this, node)
if level == 1 then this:emit("VergeC.bin.") end
this:emit(node.value)
else
- VergeC.error("COMPILE ERROR\n Unknown variable '" .. node.value .. "'.", node.index)
+ this:error("COMPILE ERROR\n Unknown variable '" .. node.value .. "'.", node.index)
end
end
View
32 src/lib/vergec/init.lua
@@ -2,6 +2,8 @@
VergeC = {}
VergeC.bin = {}
+VergeC.modules = {}
+VergeC.defines = {}
require('vergec.preprocessor')
require('vergec.tokenizer')
@@ -18,6 +20,8 @@ function VergeC.newModule()
m.ast = {}
m.compiledcode = ''
+ m.error = VergeC.error
+
m.addLine = VergeC.addLine
m.preprocess = VergeC.preprocess
m.parse = VergeC.parse
@@ -40,10 +44,10 @@ function VergeC.call(func, args)
end
function VergeC.addLine(this, ln)
- this.code = this.code .. ln .. "\n"
+ this.code = this.code .. this:preprocess(ln, string.len(this.code)) .. "\n"
end
-function VergeC.error(msg, index)
+function VergeC.error(module, msg, index)
if not index then index = module.furthestindex end
local c = module.code
local lineno = 1
@@ -65,7 +69,7 @@ function VergeC.error(msg, index)
ln = string.gsub(ln, "\t", " ")
- msg = "** VERGEC " .. msg .."\nNear line " .. lineno .. ", column " .. col .. ":\n" .. ln .. "\n" .. string.rep(" ", col-1) .. "^"
+ msg = "** VERGEC " .. msg .."\nIn " .. module.filename .. " near line " .. lineno .. ", column " .. col .. ":\n" .. ln .. "\n" .. string.rep(" ", col-1) .. "^"
v3.exit(msg)
end
@@ -73,33 +77,39 @@ end
function VergeC.loadfile(filename)
print("VERGEC: Loading file '"..filename.."'")
- module = VergeC.newModule()
+ local module = VergeC.newModule()
+ module.filename = filename
+ VergeC.modules[filename] = module
+
for line in io.lines(filename) do
module:addLine(line)
end
- module:preprocess()
--print(module.code)
local succ
module:consume(1) -- do this to consume any whitespace or comments at the beginning of the file
+
+ print("VERGEC: Parsing " .. filename .. "...")
module.ast,succ = module:parse()
if succ and module.furthestindex > string.len(module.code) then
- print("VERGEC: Parsing successful!")
+ print("VERGEC: Parsing complete.")
else
- VergeC.error("PARSING ERROR")
+ module:error("PARSING ERROR")
end
- VergeC.printAST(module.ast)
+ --VergeC.printAST(module.ast)
+ print("VERGEC: Compiling " .. filename .. "...")
module:compile()
+ print("VERGEC: Compiling complete.")
module:emit("\n-- done")
print("")
- print("LUA SOURCE:")
-
+ print(" LUA SOURCE (" .. filename .. "):")
module:outputCode(true)
+ print("")
assert(loadstring(module.compiledcode))()
@@ -146,7 +156,7 @@ function VergeC.outputCode(this, linenums)
local codelen = string.len(this.compiledcode)
while lineend < codelen do
- print(linenum .. "." .. "\t" .. ln)
+ print(" " .. linenum .. "." .. "\t" .. ln)
linenum = linenum + 1
linestart = lineend + 1
lineend = string.find(this.compiledcode, "\n", linestart, true)
View
28 src/lib/vergec/parser.lua
@@ -64,7 +64,7 @@ VergeC.parsing_expressions = {
-- expression order of operations chain
-- ordered from binds most-tightly to least-tightly
- Value = named('value',choice(
+ Value = choice(
parsex('FuncCall'),
collapse(seq(
token('IDENT'),
@@ -74,7 +74,7 @@ VergeC.parsing_expressions = {
token('NUMBER'),
token('STRING'),
seq(token('PAREN_OPEN'), parsex('Expr'), token('PAREN_CLOSE'))
- )),
+ ),
PostfixOp = choice(named('postop', collapse(seq(parsex('Value'), choice(token('OP_INCREMENT'), token('OP_DECREMENT'))))), collapse(parsex('Value'))),
PrefixOp = choice(named('preop', collapse(seq(choice(token('OP_NOT'), token('OP_INCREMENT'), token('OP_DECREMENT'), token('OP_SUB')), parsex('PostfixOp')))), collapse(parsex('PostfixOp'))),
Product = choice(collapse(named('binop', seq(parsex('PrefixOp'), collapse(one_or_more(collapse(seq(choice(token('OP_MLT'), token('OP_DIV')), parsex('PrefixOp')))))))), collapse(parsex('PrefixOp'))),
@@ -94,20 +94,30 @@ for k,v in pairs(VergeC.parsing_expressions) do if not VergeC.parsing_expression
function VergeC.parse(this, what)
local rootex = false
- if not what then what = VergeC.default_parsing_expression end
+ if not what then
+ what = VergeC.default_parsing_expression
+ this.packrat = {}
+ end
if type(what) == 'string' then
what = VergeC.parsing_expressions[what]
rootex = true
end
-
+
local startindex = this.index
local type = what.type
+ if rootex then
+ local pack = this.packrat[startindex .. ":" .. what.name]
+ if pack then
+ this.index = pack.index
+ return pack.node, pack.parsed
+ end
+ end
+
local node = { name=what.name, collapse=what.collapse, type=what.type }
local parsed = false
-
- --if what.name then print(" Parsing type: ", what.name, type) end
+ local child = nil
if type == 'DEBUG_PRINT' then
print(what.s)
@@ -245,6 +255,12 @@ function VergeC.parse(this, what)
if what.ignore then node = nil end
if node then node.index = this.index end
+ if what == VergeC.default_parsing_expression then
+ this.packrat = nil
+ elseif rootex then
+ this.packrat[startindex .. ":" .. what.name] = { node=node, parsed=parsed, index=this.index }
+ end
+
if not parsed then
this.index = startindex
return nil, false
View
41 src/lib/vergec/preprocessor.lua
@@ -1,17 +1,30 @@
--- Does preprocessing on the code
-function VergeC.preprocess(this)
- print("VERGEC: Preprocessing...")
+-- Does preprocessing on a line of code
+function VergeC.preprocess(this, ln, i)
+ local directive,params = string.match(ln, "^%s*#(%w+)%s+(.*)")
- -- TODO: Parse #includes and #defines
+ if directive then
+ if directive == 'include' then
+ params = string.gsub(params, "[\"<](.*)[\">]", "%1")
+ if not VergeC.modules[params] then VergeC.loadfile(params) end
+ elseif directive == 'define' then
+ local name,value = string.match(params, "([_%w][_%w%d]*)%s+(.*)");
+ VergeC.defines[name] = value
+ elseif directive == 'undef' then
+ local name = string.match(params, "([_%w][_%w%d]*)");
+ VergeC.defines[name] = nil
+ elseif directive then
+ this:error("PREPROCESSOR ERROR\n Unknown preprocessor directive '" .. directive .. "'.", i)
+ else
+ this:error("PREPROCESSOR ERROR\n Couldn't parse preprocessor directive.", i)
+ end
+ ln = ""
+ else
+ local k,v
+
+ for k,v in pairs(VergeC.defines) do
+ if v then ln = string.gsub(ln, k .. "([^_%w%d])", v .. "%1") end
+ end
+ end
- -- Strip comments
- -- comment skipping has been moved to VergeC.consume in tokenizer.lua
- --this.code = string.gsub(this.code, "//.-\n", "\n")
- --
- --for comm in string.gmatch(this.code, "/%*(.-)%*/") do
- -- local repl = string.gsub(comm, "[^\n]", "")
- -- this.code = string.gsub(this.code, "/%*(.-)%*/", repl, 1)
- --end
-
- --print(this.code)
+ return ln
end
View
14 src/lib/vergec/tokenizer.lua
@@ -1,7 +1,6 @@
-
-- Lexing functions
-- Define possible tokens
-tokens = {
+VergeC.tokens = {
{'OP_EQ','=='}, {'OP_NE','!='},{'OP_ASSIGN','='},
{'OP_LTE','<='},{'OP_GTE','>='},{'OP_LTE', '<='},{'OP_GTE','>='},{'OP_LT', '<'},{'OP_GT','>'},
{'OP_AND','%&%&'},{'OP_OR','%|%|'},{'OP_BSL','<<'},{'OP_BSR','>>'},
@@ -24,7 +23,7 @@ function VergeC.peek(this)
local index = this.index
local codelen = string.len(code)
- for x,p in ipairs(tokens) do
+ for x,p in ipairs(VergeC.tokens) do
local m = string.match(code, '^'..p[2], index)
if m then
if p[1] == 'STRING' then
@@ -73,7 +72,7 @@ function VergeC.peek(this)
return p[1], m, index
end
end
-
+
return nil, nil, index
end
@@ -82,12 +81,11 @@ function VergeC.consume(this, index)
this.index = index
-- skip whitespace and comments
- local m = true -- just stuff this with a not-false value so the loop executes at least once
- while m do
- m = string.match(this.code, "^%s+", this.index) or string.match(this.code, "^//.-\n", this.index) or string.match(this.code, "^/%*.-%*/", this.index)
+ repeat
+ local m = string.match(this.code, "^%s+", this.index) or string.match(this.code, "^//.-\n", this.index) or string.match(this.code, "^/%*.-%*/", this.index)
--print("Consuming whitespace <" .. tostring(m) .. ">")
if m then this.index = this.index + string.len(m) end
- end
+ until not m
if this.index > this.furthestindex then this.furthestindex = this.index end
end
View
96 system.vc
@@ -1,96 +1,8 @@
-//int x = 5;
-//int y = 1;
-//int arr[5];
+#include "inc.vc"
-struct pet {
- string type;
- string name;
-};
-
-struct user {
- int id;
- string name;
- int coolness;
- pet pets[15];
- int bank_account_numbers[4];
-};
-
-user mcgrue;
+#define A_CON 1
+#define A_CONSTANT 5
void autoexec() {
- user vecna;
-
- mcgrue.name = "Ben";
- vecna.name = "Also Ben";
- mcgrue.pets[0].name = "Test";
- mcgrue.pets[0].type = "Grue";
-
- log(mcgrue.pets[0].name);
- log(mcgrue.pets[0].type);
+ log(add(A_CONSTANT, 2));
}
-
- //int x = 4747;
- //
- //for (int i = 0; i < 10; i++) {
- // if ( i == 5) continue;
- // if ( i == 7) break;
- // log(i);
- //}
- //
- //arr[0] = x++;
- //arr[1] = x++;
- //arr[2] = x++;
- //arr[3] = x++;
- //arr[4] = x++;
- //
- //for ( int i = 0; i < 5; i++ ) {
- // log(arr[i]);
- //}
-
-// int x = 1;
-//
-// y = ++x;
-//
-// if ( x )
-// log("blart");
-//
-//
-// while ( x < 10 ) {
-// x++;
-// }
-//
-// log(x);
-//
-// x = add(5,6);
-//
-// log(x);
-//}
-//
-//int add(int x, int y) {
-// return x + y;
-//}
-
-//void autoexec() {
-// if ( y && x ) {
-// log("True!");
-// }
-//
-// int x = -2;
-// x = add(x);
-// log(x);
-//
-// x = -1;
-// log(abs(x));
-//}
-
-//int add(int x = 1, int y = 1) {
-// //return x + y + 3;
-// //return x + y * 1 / 1 + y - 0;
-// return x + y;
-//}
-//
-//int abs(int x) {
-// if ( x > 0 )
-// return x;
-// return -x;
-//}
View
3  verge.cfg
@@ -1,3 +1,4 @@
nosound 0
dx9 0
-lua 1
+lua 1
+auto_max 0
Please sign in to comment.
Something went wrong with that request. Please try again.