From 3d04f6a120f745fb5127de660de228ae5e341ec3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Fern=C3=A1ndez?= Date: Sat, 8 Oct 2011 23:24:24 +0200 Subject: [PATCH] Empiezo el compilador --- compiler/.gitignore | 3 + compiler/ast.js | 118 +++++++++++++++++++++++++++++++++++++++ compiler/c++.pegjs | 123 +++++++++++++++++++++++++++++++++++++++++ compiler/cc.js | 11 ++++ compiler/gen_parser.sh | 3 + compiler/preamble.js | 3 + compiler/test.cc | 4 ++ index.html | 36 ++++++------ 8 files changed, 284 insertions(+), 17 deletions(-) create mode 100644 compiler/.gitignore create mode 100644 compiler/ast.js create mode 100644 compiler/c++.pegjs create mode 100755 compiler/cc.js create mode 100755 compiler/gen_parser.sh create mode 100644 compiler/preamble.js create mode 100644 compiler/test.cc diff --git a/compiler/.gitignore b/compiler/.gitignore new file mode 100644 index 0000000..88b110a --- /dev/null +++ b/compiler/.gitignore @@ -0,0 +1,3 @@ +c++-parser.js +c++.js +examples diff --git a/compiler/ast.js b/compiler/ast.js new file mode 100644 index 0000000..351884e --- /dev/null +++ b/compiler/ast.js @@ -0,0 +1,118 @@ + +var ast = ast || {}; + +/* Model of inheritance */ + +ast.__inherit__ = (function() { + var F = function (typename) { + this.typename = typename; + }; + return function (typename, C, P) { + F.prototype = P.prototype; + C.prototype = new F(typename); + C.uber = P.prototype; + C.prototype.constructor = C; + } +})(); + +/* Node type */ + +ast.Node = function () {}; + +ast.Node.prototype = { + typename: "Node", + accept: function (visitor) { + var methodName = 'v' + this.typename; + if (methodName in visitor) { + visitor[methodName].call(visitor, this); + } else if ('vNode' in visitor) { + visitor['vNode'].call(visitor, this); + } + }, +}; + +ast.NodeList = function() { + this.children = []; +} + +ast.__inherit__("NodeList", ast.NodeList, ast.Node); + +ast.NodeList.prototype.add = function (obj) { + this.children.push(obj); +} + + +/* Construct node types */ + +function nodeTypeMaker(Base) { + return function (typename) { + var NewType = function (obj) { + for (var prop in obj) { + if (obj.hasOwnProperty(prop)) { + this[prop] = obj[prop]; + } + } + } + ast.__inherit__(typename, NewType, Base); + ast[typename] = NewType; + } +} + +ast.makeNodeType = nodeTypeMaker(ast.Node); + +/* Create Node Types */ + + +var types = [ + "IncludeDirective", + "UsingDirective", + "ForStmt", + "WhileStmt", +]; +for (var i in types) { + ast.makeNodeType(types[i]); +} + +/* Visitors */ + +ast.reportVisitor = { + vNode: function(obj) { + console.log("seen a Node!"); + }, + vIncludeDirective: function (obj) { + console.log("seen an Include!"); + }, + vNodeList: function (obj) { + console.log("seen a NodeList!"); + for (var i in obj.children) { + obj.children[i].accept(this); + } + } +} + +ast.nodeCount = function () { + this.count = 0; +} + +ast.nodeCount.prototype = { + vNode: function(obj) { + this.count++; + } +} + +/* test... */ + +var util = require('util'); + +var i = new ast.IncludeDirective({ name: "iostream" }); +var n = new ast.Node(); +var L = new ast.NodeList(); +L.add(i); +L.add(n); +console.log(util.inspect(L, true, 4)) + +L.accept(ast.reportVisitor); + +var nc = new ast.nodeCount(); +i.accept(nc); +console.log(nc.count); diff --git a/compiler/c++.pegjs b/compiler/c++.pegjs new file mode 100644 index 0000000..779d473 --- /dev/null +++ b/compiler/c++.pegjs @@ -0,0 +1,123 @@ + +start = + __ program:Program __ { return program; } + +WhiteSpace = [ \t\f] +LineTerminator = [\n\r] +LineTerminatorSeq = "\n" / "\r\n" / "\r" +SourceCharacter = . + +__ = + (WhiteSpace / LineTerminatorSeq / Comment)* + +_ = + (WhiteSpace / MultiLineCommentOneLine / SingleLineComment)* + +Literal = [0-9] + +MultiLineComment = + "/*" (!"*/" SourceCharacter)* "*/" + +MultiLineCommentOneLine = + "/*" (!("*/" / LineTerminator) SourceCharacter)* "*/" + +SingleLineComment = + "//" (!LineTerminator SourceCharacter)* + +Comment = + MultiLineComment / + SingleLineComment + +Identifier = + name:([_A-Za-z] [_A-Za-z0-9]*) { + return new ast.Identifier(name); + } + +Type = + "int" / + "char" / + "float" + +FormalParameter = + type:Type _ name:Identifier { + return { + type: type, + name: name + } + } + +FormalParameterList = + head:FormalParameter tail:(__ "," __ FormalParameter)* { + var result = [head]; + for (var i = 0; i < tail.length; i++) { + result.push(tail[i][3]); + } + return result; + } + +VarDecl = + name:Identifier (__ "=" __ value:Literal)? { + return { + name: name, + value: value, + } + } + +VarDeclList = + head:VarDecl tail:(__ "," __ VarDecl) { + var result = [head]; + for (var i = 0; i < tail.length; i++) { + result.push(tail[i][3]); + } + return result; + } + +VarDeclStmt = + type:Type __ list:VarDeclList { + return new ast.VarDeclStmt(type, list); + } + +Stmt = + VarDeclStmt + +StmtList = + head:Stmt tail:(__ Stmt)* { + var result = [head]; + for (var i = 0; i < tail.length; i++) { + result.push(tail[i][1]); + } + return result; + } + + +FunctionBody = + StmtList + +FunctionDef = + Type _ name:Identifier + "(" __ params:FormalParameterList? __ ")" __ + "{" __ elements:FunctionBody? __ "}" { + return new ast.Function(name, params, elements); + } + +IncludeDirective "include" = + "#include" _ [<"] file:[a-z]* [>"] { + console.log("include!"); + return new ast.Include(file) + } + +ProgramPart = + IncludeDirective / + FunctionDef / + Comment + +Program = + head:ProgramPart tail:(__ ProgramPart)* { + var result = [head]; + for (var i = 0; i < tail.length; i++) { + result.push(tail[i][1]); + } + return new ast.Program(result); + } + + diff --git a/compiler/cc.js b/compiler/cc.js new file mode 100755 index 0000000..01dd88f --- /dev/null +++ b/compiler/cc.js @@ -0,0 +1,11 @@ +#!/usr/bin/env node + +var util = require('util'); +var fs = require('fs'); +var cc = require('c++-parser'); + +fs.readFile('test.cc', 'utf-8', function (err, data) { + var tree = cc.parse(data); + console.log(util.inspect(tree, true, null)); +}); + diff --git a/compiler/gen_parser.sh b/compiler/gen_parser.sh new file mode 100755 index 0000000..8606628 --- /dev/null +++ b/compiler/gen_parser.sh @@ -0,0 +1,3 @@ +#!/bin/bash +pegjs c++.pegjs c++.js +cat preamble.js c++.js > c++-parser.js \ No newline at end of file diff --git a/compiler/preamble.js b/compiler/preamble.js new file mode 100644 index 0000000..28d2558 --- /dev/null +++ b/compiler/preamble.js @@ -0,0 +1,3 @@ + +var ast = require('ast'); + diff --git a/compiler/test.cc b/compiler/test.cc new file mode 100644 index 0000000..f4be74a --- /dev/null +++ b/compiler/test.cc @@ -0,0 +1,4 @@ +#include + +int main() { +} diff --git a/index.html b/index.html index 4bd8442..6e48008 100644 --- a/index.html +++ b/index.html @@ -1,23 +1,25 @@ - - - - - - - - - + + + + + + + + + -
-
Compila
-
Executa
-
Preferències
-
-
-
+
+
Compila
+
Executa
+
Preferències
+
+
+