clean:
rm -f pretty *.6 *~
-pretty.6: parser.6 printer.6 platform.6 scanner.6
+pretty.6: printer.6 platform.6 compilation.6
+
+compilation.6: scanner.6 parser.6 ast.6
printer.6: ast.6 scanner.6
PRETTY_OBJS = \
ast.o \
pretty.o \
+ compilation.go \
parser.o \
platform.o \
printer.o \
clean:
rm -f pretty *.o *~
-pretty.o: parser.o printer.o platform.o scanner.o flag.o
-parser.o: ast.o scanner.o utils.o printer.o
+pretty.o: printer.o platform.o compilation.o
-scanner.o: utils.o platform.o
+compilation.o: scanner.o parser.o ast.o
+
+printer.o: ast.o scanner.o
+
+parser.o: scanner.o utils.o printer.o ast.o
ast.o: scanner.o
+scanner.o: utils.o platform.o
+
+
flag.o: fmt.o
$(GO) -O2 -c -g $(GOROOT)/src/lib/flag.go
x := P.ParseIdent();
t = AST.NewType(x.pos, Scanner.IDENT);
t.expr = x;
+ } else if P.tok == Scanner.ELLIPSIS {
+ t = AST.NewType(P.pos, Scanner.ELLIPSIS);
+ P.Next();
} else {
t = P.ParseType();
}
}
-func (P *Parser) ParseVarDeclList(list *AST.List) {
+func (P *Parser) ParseVarDeclList(list *AST.List, ellipsis_ok bool) {
P.Trace("VarDeclList");
// parse a list of types
i0 := list.len();
- list.Add(P.ParseVarDecl(i0 > 0));
- for P.tok == Scanner.COMMA {
- P.Next();
+ for {
list.Add(P.ParseVarDecl(i0 > 0));
+ if P.tok == Scanner.COMMA {
+ P.Next();
+ } else {
+ break;
+ }
}
- var typ *AST.Type;
- if i0 > 0 {
+ typ := P.TryType();
+ if typ == nil && P.tok == Scanner.ELLIPSIS {
+ typ = AST.NewType(P.pos, Scanner.ELLIPSIS);
+ P.Next();
+ }
+
+ if i0 > 0 && typ == nil {
// not the first parameter section; we must have a type
- typ = P.ParseType();
- } else {
- // first parameter section; we may have a type
- typ = P.TryType();
+ P.Error(P.pos, "type expected");
+ typ = AST.BadType;
}
-
+
// convert the list into a list of (type) expressions
if typ != nil {
// all list entries must be identifiers
} else {
// all list entries are types
// convert all type entries into type expressions
- for i, n := i0, list.len(); i < n; i++ {
+ if i0 > 0 {
+ panic("internal parser error");
+ }
+
+ for i, n := 0, list.len(); i < n; i++ {
t := list.at(i).(*AST.Type);
list.set(i, AST.NewTypeExpr(t));
}
}
-func (P *Parser) ParseParameterList() *AST.List {
+func (P *Parser) ParseParameterList(ellipsis_ok bool) *AST.List {
P.Trace("ParameterList");
list := AST.NewList();
- P.ParseVarDeclList(list);
+ P.ParseVarDeclList(list, ellipsis_ok);
for P.tok == Scanner.COMMA {
P.Next();
- P.ParseVarDeclList(list);
+ P.ParseVarDeclList(list, ellipsis_ok);
}
P.Ecart();
}
-func (P *Parser) ParseParameters() *AST.Type {
+func (P *Parser) ParseParameters(ellipsis_ok bool) *AST.Type {
P.Trace("Parameters");
t := AST.NewType(P.pos, Scanner.STRUCT);
P.Expect(Scanner.LPAREN);
if P.tok != Scanner.RPAREN {
- t.list = P.ParseParameterList();
+ t.list = P.ParseParameterList(ellipsis_ok);
}
P.Expect(Scanner.RPAREN);
var t *AST.Type;
if P.tok == Scanner.LPAREN {
- t = P.ParseParameters();
+ t = P.ParseParameters(false);
} else {
typ := P.TryType();
if typ != nil {
P.Trace("FunctionType");
t := AST.NewType(P.pos, Scanner.LPAREN);
- t.list = P.ParseParameters().list; // TODO find better solution
+ t.list = P.ParseParameters(true).list; // TODO find better solution
t.elt = P.ParseResult();
P.Ecart();
P.Next();
t.list = AST.NewList();
for P.tok == Scanner.IDENT {
- P.ParseVarDeclList(t.list);
+ P.ParseVarDeclList(t.list, false);
if P.tok != Scanner.RBRACE {
P.Expect(Scanner.SEMICOLON);
}
var recv *AST.Type;
if P.tok == Scanner.LPAREN {
pos := P.pos;
- recv = P.ParseParameters();
+ recv = P.ParseParameters(true);
if recv.nfields() != 1 {
P.Error(pos, "must have exactly one receiver");
}
import Flag "flag"
import Platform "platform"
-import Scanner "scanner"
-import Parser "parser"
import Printer "printer"
+import Compilation "compilation"
var (
+ flags Compilation.Flags;
silent = Flag.Bool("s", false, nil, "silent mode: no pretty print output");
- verbose = Flag.Bool("v", false, nil, "verbose mode: trace parsing");
- sixg = Flag.Bool("6g", true, nil, "6g compatibility mode");
- columns = Flag.Bool("columns", Platform.USER == "gri", nil, "print column info in error messages");
- testmode = Flag.Bool("t", false, nil, "test mode: interprets /* ERROR */ and /* SYNC */ comments");
- tokenchan = Flag.Bool("token_chan", false, nil, "use token channel for scanner-parser connection");
+ verbose = Flag.Bool("v", false, &flags.verbose, "verbose mode: trace parsing");
+ sixg = Flag.Bool("6g", true, &flags.sixg, "6g compatibility mode");
+ deps = Flag.Bool("d", false, &flags.deps, "print dependency information only");
+ columns = Flag.Bool("columns", Platform.USER == "gri", &flags.columns, "print column info in error messages");
+ testmode = Flag.Bool("t", false, &flags.testmode, "test mode: interprets /* ERROR */ and /* SYNC */ comments");
+ tokenchan = Flag.Bool("token_chan", false, &flags.tokenchan, "use token channel for scanner-parser connection");
)
sys.exit(1);
}
- scanner := new(Scanner.Scanner);
- scanner.Open(src_file, src, columns.BVal(), testmode.BVal());
+ C := Compilation.Compile(src_file, src, &flags);
- var tstream *<-chan *Scanner.Token;
- if tokenchan.BVal() {
- tstream = scanner.TokenStream();
- }
-
- parser := new(Parser.Parser);
- parser.Open(verbose.BVal(), sixg.BVal(), scanner, tstream);
-
- prog := parser.ParseProgram();
-
- if scanner.nerrors > 0 {
+ if C.nerrors > 0 {
sys.exit(1);
}
+
+ if flags.deps {
+ print("deps\n");
+ panic("UNIMPLEMENTED");
+ return;
+ }
- if !silent.BVal() && !testmode.BVal() {
+ if !silent.BVal() && !flags.testmode {
var P Printer.Printer;
- (&P).Program(prog);
+ (&P).Program(C.prog);
}
}
}
func (P *Printer) Fields(list *AST.List) {
- P.OpenScope(" {");
+ P.OpenScope("{");
var prev int;
for i, n := 0, list.len(); i < n; i++ {
x := list.at(i).(*AST.Expr);
if i > 0 {
if prev == Scanner.TYPE {
- P.String(0, ";");
- P.newl = 1;
+ P.semi, P.newl = true, 1;
} else if prev == x.tok {
P.String(0, ", ");
} else {
P.Parameters(0, t.elt.list);
}
+ case Scanner.ELLIPSIS:
+ P.String(t.pos, "...");
+
default:
P.Error(t.pos, t.tok, "type");
}