Permalink
Browse files

(initial) almost working parser

  • Loading branch information...
indutny committed Feb 10, 2012
0 parents commit f3b1ebf3a839e32fcafa14b21af304aa32a24e93
Showing with 1,339 additions and 0 deletions.
  1. +6 −0 .gitignore
  2. +65 −0 Makefile
  3. +86 −0 README.md
  4. +11 −0 include/dotlang.h
  5. +197 −0 src/ast.h
  6. +6 −0 src/dotlang.cc
  7. +12 −0 src/fullgen.h
  8. +205 −0 src/lexer.cc
  9. +119 −0 src/lexer.h
  10. +374 −0 src/parser.cc
  11. +73 −0 src/parser.h
  12. +87 −0 src/utils.h
  13. 0 src/x64/fullgen.cc
  14. +43 −0 test/test-parser.cc
  15. +55 −0 test/test.h
@@ -0,0 +1,6 @@
+*.o
+*.a
+*.dSYM
+/test/*
+!/test/*.h
+!/test/*.cc
@@ -0,0 +1,65 @@
+CPPFLAGS += -Wall -Wextra -Wno-unused-parameter
+CPPFLAGS += -fPIC -Iinclude
+CPPFLAGS += -fno-strict-aliasing
+CPPFLAGS += -g
+
+ifeq ($(shell sh -c 'uname -s 2>/dev/null'),Darwin)
+ OS = Darwin
+else
+ OS = Linux
+endif
+
+ifeq ($(MODE),release)
+ CPPFLAGS += -O3
+ CPPFLAGS += -DNDEBUG
+endif
+
+ifeq ($(ARCH),)
+ ARCH = $(shell sh -c 'uname -m | sed -e "s/i.86/i386/;s/x86_64/x64/;s/amd64/x64/"')
+endif
+
+all: dotlang.a
+
+OBJS += src/dotlang.o
+OBJS += src/lexer.o
+OBJS += src/parser.o
+
+ifeq (0,1)
+ ifeq ($(ARCH),i386)
+ ifeq ($(OS),Darwin)
+ CPPFLAGS += -arch i386
+ else
+ CPPFLAGS += -m32
+ endif
+ OBJS += src/ia32/assembler-ia32.o
+ OBJS += src/ia32/codegen-ia32.o
+ else
+ OBJS += src/x64/assembler-x64.o
+ OBJS += src/x64/codegen-x64.o
+ endif
+endif
+
+ifeq ($(OS),Darwin)
+ CPPFLAGS += -D__DARWIN
+else
+ CPPFLAGS += -D__LINUX
+endif
+
+dotlang.a: $(OBJS)
+ $(AR) rcs dotlang.a $(OBJS)
+
+src/%.o: src/%.cc
+ $(CXX) $(CPPFLAGS) -Isrc -c $< -o $@
+
+TESTS += test/test-parser
+
+test: $(TESTS)
+ @test/test-parser
+
+test/%: test/%.cc dotlang.a
+ $(CXX) $(CPPFLAGS) -Isrc $< -o $@ dotlang.a
+
+clean:
+ rm -f $(OBJS) dotlang.a
+
+.PHONY: all test
@@ -0,0 +1,86 @@
+# Dot lang
+
+```dot
+// Keywords: return, scope, new, if, else, while, break
+
+// Primitives
+1
+'abc'
+"abc"
+[1, 2, 3]
+{ a: 1, 'b': 2, "c": 3 }
+
+// Variables and objects
+a = 1
+a.b = "abc"
+a.b.c = a
+
+// Functions
+a() {
+ return 1
+}
+a()
++(b, c) {
+ return binding_plus(b, c)
+}
+b + c
++(b, c)
++any_stuff(b, c) {
+ return b + c;
+}
+b +any_stuff c
+
+// Blocks
+{
+ scope a
+}
+
+// Expr blocks
+({
+ a = 1
+})(x)
+// is equivalent to
+x.a = 1
+```
+
+Grammar:
+
+```
+code := statement*
+
+scope := "scope" (name ",")* name CR
+block := "{" scope? statement* "}"
+args := ((name ",")* name)?
+
+array := "[" ((expr ",")* expr)? "]"
+objectKv := (name|string) ":" expr
+object := "{" ((objectKv ",")* objectKv)? "}"
+
+primary := name | number | string | array | object | "(" expr ")"
+member := primary ("[" expression "]" | "." name)*
+callOrFun := member "(" ((expr ",")* expr)? ")" block? |
+ member? "(" ((expr ",")* expr)? ")" block
+assign := member "=" expr
+
+prefix := ("!" | "--" | "++") expr
+postfix := expr ("--" | "++")
+
+binop1 := expr (("*" | "/") expr)*
+binop2 := binop1 (("+" | "-") binop1)*
+binop3 := binop2 (("&" | "|" | "^") binop2)*
+binop4 := binop3 (("&&" | "||") binop3)*
+binop5 := binop4 ((">" | "<" | "<=" | ">=") binop4)*
+binop := binop5 (("==" | "===" | "!=" | "!==") binop5)*
+
+blockExpr := block
+
+return := "return" expr?
+break := "break"
+if := "if" "(" expr ")" block ("else" block)?
+while := "while" "(" expr ")" block
+
+statement := (return | break | if | while | block | expr) CR
+
+expr := binop | prefix | postfix |
+ blockExpr | assign | callOrFun | member
+```
@@ -0,0 +1,11 @@
+#ifndef _INCLUDE_DOTLANG_H_
+#define _INCLUDE_DOTLANG_H_
+
+namespace dotlang {
+
+class Dot {
+};
+
+} // namespace dotlang
+
+#endif // _INCLUDE_DOTLANG_H_
197 src/ast.h
@@ -0,0 +1,197 @@
+#ifndef _SRC_AST_H_
+#define _SRC_AST_H_
+
+#include "utils.h" // List
+#include "lexer.h" // lexer
+
+namespace dotlang {
+
+#define TYPE_MAPPING(V)\
+ V(kName)\
+ V(kNumber)\
+ V(kString)\
+ V(kTrue)\
+ V(kFalse)\
+ V(kNil)\
+ V(kAdd)\
+ V(kSub)\
+ V(kDiv)\
+ V(kMul)\
+ V(kBAnd)\
+ V(kBOr)\
+ V(kBXor)\
+ V(kEq)\
+ V(kStrictEq)\
+ V(kNe)\
+ V(kStrictNe)\
+ V(kLt)\
+ V(kGt)\
+ V(kLe)\
+ V(kGe)\
+ V(kLOr)\
+ V(kLAnd)
+
+// Base class
+class AstNode {
+ public:
+ enum Type {
+ kBlock,
+ kBlockExpr,
+ kMember,
+ kAssign,
+ kIf,
+ kWhile,
+ kBreak,
+ kReturn,
+ kFunction,
+
+ // Prefixes
+ kPreInc,
+ kPreDec,
+ kNot,
+
+ // Postfixes,
+ kPostInc,
+ kPostDec,
+
+ // Binop
+#define MAP_DF(x) x,
+ TYPE_MAPPING(MAP_DF)
+#undef MAP_DF
+
+ kNop
+ };
+
+ AstNode(Type type_) : type(type_) {
+ value = NULL;
+ length = 0;
+ children.allocated = true;
+ }
+
+ inline static Type ConvertType(Lexer::TokenType type) {
+ switch (type) {
+#define MAP_DF(x) case Lexer::x: return x;
+ TYPE_MAPPING(MAP_DF)
+#undef MAP_DF
+ default:
+ return kNop;
+ }
+ }
+
+ AstNode* FromToken(Lexer::Token* tok) {
+ value = tok->value;
+ length = tok->length;
+
+ return this;
+ }
+
+
+ Type type;
+ const char* value;
+ uint32_t length;
+
+ List<AstNode*> children;
+};
+#undef TYPE_MAPPING
+
+
+class FunctionLiteral : public AstNode {
+ public:
+ FunctionLiteral(AstNode* variable_) : AstNode(kFunction) {
+ variable = variable_;
+ body = NULL;
+ args.allocated = true;
+ }
+
+ ~FunctionLiteral() {
+ delete variable;
+ delete body;
+ }
+
+ bool CheckDeclaration() {
+ // Function without body is a call
+ if (body == NULL) {
+ // So it should have a name
+ if (variable == NULL) return false;
+ return true;
+ }
+
+ // Name should not be "a.b.c"
+ if (variable != NULL && variable->type != kName) return false;
+
+ // Arguments should be a kName, not expressions
+ List<AstNode*>::Item* head = args.Head();
+ while (head != NULL) {
+ if (head->value->type != kName) return false;
+ head = args.Next(head);
+ }
+
+ // Body should be a block
+ if (body->type != kBlock) return false;
+
+ return true;
+ }
+
+ AstNode* variable;
+ List<AstNode*> args;
+ AstNode* body;
+};
+
+
+class IfStmt : public AstNode {
+ public:
+ IfStmt(AstNode* condition, AstNode* body_, AstNode* else_) : AstNode(kIf) {
+ cond = condition;
+ body = body_;
+ else_body = else_;
+ }
+
+ ~IfStmt() {
+ delete cond;
+ delete body;
+ delete else_body;
+ }
+
+ AstNode* cond;
+ AstNode* body;
+ AstNode* else_body;
+};
+
+
+class WhileStmt : public AstNode {
+ public:
+ WhileStmt(AstNode* condition, AstNode* body_) : AstNode(kWhile) {
+ cond = condition;
+ body = body_;
+ }
+
+ ~WhileStmt() {
+ delete cond;
+ delete body;
+ }
+
+ AstNode* cond;
+ AstNode* body;
+};
+
+
+class AssignExpr : public AstNode {
+ public:
+ AssignExpr(AstNode* variable_, AstNode* value_) : AstNode(kAssign) {
+ variable = variable_;
+ value = value_;
+ }
+
+ ~AssignExpr() {
+ delete variable;
+ delete value;
+ }
+
+ AstNode* variable;
+ AstNode* value;
+};
+
+
+} // namespace dotlang
+
+#endif // _SRC_AST_H_
@@ -0,0 +1,6 @@
+#include "dotlang.h"
+
+
+namespace dotlang {
+
+} // namespace dotlang
@@ -0,0 +1,12 @@
+#ifndef _SRC_FULLGEN_H_
+#define _SRC_FULLGEN_H_
+
+namespace dotlang {
+
+class Fullgen {
+ public:
+};
+
+} // namespace dotlang
+
+#endif // _SRC_FULLGEN_H_
Oops, something went wrong.

0 comments on commit f3b1ebf

Please sign in to comment.