Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Now having the lexer and the parser generate a proper AST! Also havin…

…g the AST "compilation" phase, even tough it as not been tested so far.
  • Loading branch information...
commit 96e676532e68317477ed0673c7c27a4c238082a7 1 parent 4308be1
@sthilaid authored
View
253 dcpu/parser/dcpuAST.go
@@ -0,0 +1,253 @@
+package parser
+
+import "fmt"
+import "dcpu"
+
+//*****************************************************************************
+
+//--------------------
+// program description
+//--------------------
+
+type DcpuProgram struct {
+ expressions []DcpuExpression
+ labels map[DcpuLabel]byte
+}
+
+func (prog DcpuProgram)processLabels() {
+ var currentSize byte = 0
+ prog.labels = make(map[DcpuLabel]byte)
+
+ for _, expr := range prog.expressions {
+ if expr.label != "" {
+ prog.labels[expr.label] = currentSize
+ currentSize += expr.Size(prog)
+ }
+ }
+}
+
+func (prog DcpuProgram)Code() []dcpu.Word {
+ code := []dcpu.Word{}
+ for _, expr := range prog.expressions {
+ code = append(code, expr.Code(prog)...)
+ }
+ return code
+}
+
+func (prog DcpuProgram)String() string {
+ str := "Program {"
+ for _,expr := range prog.expressions {
+ str += expr.String() + ", "
+ }
+ return str + "}\n"
+}
+
+//-----------------------
+// Expression description
+//-----------------------
+
+type DcpuExpression struct {
+ inst DcpuInstruction
+ a DcpuOperand
+ b DcpuOperand
+ label DcpuLabel
+}
+
+func (exp DcpuExpression)Code(prog DcpuProgram) []dcpu.Word {
+ opCode := exp.inst.Code()
+ a := exp.a.Code(prog)
+ b := exp.b.Code(prog)
+
+ binaryExpr := b[0] << 10 + a[0] << 4 + opCode
+
+ intermediateResult := append([]dcpu.Word{binaryExpr}, a[1:]...)
+ return append(intermediateResult, b[1:]...)
+}
+
+func (exp DcpuExpression)Size(prog DcpuProgram) byte {
+ return byte(1) + exp.a.Size(prog) + exp.b.Size(prog)
+}
+
+func (exp DcpuExpression)String() string {
+ return string(exp.inst) +" "+ exp.a.String() +", "+ exp.b.String()
+}
+
+//*****************************************************************************
+
+//-----------------------------
+// instruction node description
+//-----------------------------
+
+type DcpuInstruction string
+
+func (inst DcpuInstruction)Code() dcpu.Word {
+ switch inst {
+ case "SET": return 0x1
+ case "ADD": return 0x2
+ case "SUB": return 0x3
+ case "MUL": return 0x4
+ case "DIV": return 0x5
+ case "MOD": return 0x6
+ case "SHL": return 0x7
+ case "SHR": return 0x8
+ case "AND": return 0x9
+ case "BOR": return 0xa
+ case "XOR": return 0xb
+ case "IFE": return 0xc
+ case "IFN": return 0xd
+ case "IFG": return 0xe
+ case "IFB": return 0xf
+ case "JSR": return 0x10
+ }
+ panic(fmt.Sprintf("unknown instruction: %s", inst))
+}
+
+//*****************************************************************************
+
+//---------------------------
+// operand node meta description
+//---------------------------
+
+type DcpuOperand interface {
+ Code(prog DcpuProgram) []dcpu.Word
+ Size(prog DcpuProgram) byte
+ String() string
+}
+
+//---------------------------
+// reference node description
+//---------------------------
+
+type DcpuReference struct {
+ ref interface {
+ ReferenceCode(prog DcpuProgram) []dcpu.Word
+ ReferenceSize(prog DcpuProgram) byte
+ String() string
+ }
+}
+func (refNode DcpuReference)Code(prog DcpuProgram) []dcpu.Word {
+ return refNode.ref.ReferenceCode(prog)
+}
+
+func (refNode DcpuReference)Size(prog DcpuProgram) byte {
+ return refNode.ref.ReferenceSize(prog)
+}
+
+func (refNode DcpuReference)String() string {
+ return refNode.ref.String()
+}
+
+//---------------------------
+// register node description
+//---------------------------
+
+type DcpuRegister string
+
+func (reg DcpuRegister) Code(prog DcpuProgram) []dcpu.Word {
+ registers := []DcpuRegister{"A", "B", "C", "X", "Y", "Z", "I", "J"}
+ for i, r := range registers {
+ if reg == r {
+ return []dcpu.Word{dcpu.Word(i)}
+ }
+ }
+ panic(fmt.Sprintf("Couldn't find register: %s", reg))
+}
+func (reg DcpuRegister) Size(prog DcpuProgram) byte {
+ return 0
+}
+
+func (reg DcpuRegister) ReferenceCode(prog DcpuProgram) []dcpu.Word {
+ // register Code always returns one Word
+ return []dcpu.Word{reg.Code(prog)[0] + 0x8}
+}
+
+func (reg DcpuRegister) ReferenceSize(prog DcpuProgram) byte {
+ return 0
+}
+
+func (reg DcpuRegister) String() string {
+ return string(reg)
+}
+
+//--------------------------------
+// litteral value node description
+//--------------------------------
+
+type DcpuLitteral dcpu.Word
+
+func (lit DcpuLitteral)isEmbeded() bool {
+ return lit < 0x20
+}
+
+func (lit DcpuLitteral)Code(prog DcpuProgram) []dcpu.Word {
+ value := dcpu.Word(lit)
+ if lit.isEmbeded() {
+ // embeded litteral
+ return []dcpu.Word{value + 0x20}
+ }
+ // else next word
+ return []dcpu.Word{0x1f, value}
+}
+
+func (lit DcpuLitteral)Size(prog DcpuProgram) byte {
+ if lit.isEmbeded() {
+ return 0
+ }
+ return 1
+}
+
+func (lit DcpuLitteral)ReferenceCode(prog DcpuProgram) []dcpu.Word {
+ return []dcpu.Word{0x1e, dcpu.Word(lit)}
+}
+
+func (lit DcpuLitteral)ReferenceSize(prog DcpuProgram) byte {
+ return 1
+}
+
+func (lit DcpuLitteral)String() string {
+ return fmt.Sprintf("0x%x", uint16(lit))
+}
+
+//--------------------------------
+// sum regerence node description
+//--------------------------------
+
+type DcpuSum struct {
+ reg DcpuRegister
+ lit DcpuLitteral
+}
+
+func (sum DcpuSum)ReferenceCode(prog DcpuProgram) []dcpu.Word {
+ // registers Code always returns 1 word
+ return []dcpu.Word{sum.reg.Code(prog)[0] + 0x10, dcpu.Word(sum.lit)}
+}
+
+func (sum DcpuSum)ReferenceSize(prog DcpuProgram) byte {
+ return 1
+}
+
+func (sum DcpuSum)String() string {
+ return sum.lit.String() +" + "+ sum.reg.String()
+}
+
+//--------------------------------
+// label node description
+//--------------------------------
+
+type DcpuLabel string
+
+func (label DcpuLabel)Code(prog DcpuProgram) []dcpu.Word {
+ value := prog.labels[label]
+ lit := DcpuLitteral(value)
+ return lit.Code(prog)
+}
+
+func (label DcpuLabel)Size(prog DcpuProgram) byte {
+ value := prog.labels[label]
+ lit := DcpuLitteral(value)
+ return lit.Size(prog)
+}
+
+func (label DcpuLabel)String() string {
+ return string(label)
+}
View
108 dcpu/parser/dcpuAssembly.y
@@ -1,37 +1,111 @@
+// -*- mode: go -*-
%{
package parser
import "fmt"
-import "dcpu"
-type DCPUnative []dcpu.Word
-
-var dcpuLexerReturnValue DCPUnative = DCPUnative{}
+var ParsedProgram DcpuProgram
%}
%start program
-%token <vvar> instruction
-%token <vvar> register
-%token <vvar> label
-%token <numb> litteral
+%token <inst> instruction
+%token <reg> register
+%token <lab> label
+%token <lit> litteral
+%type <expr> expression
+%type <operand> operand
+%type <ref> reference
+%type <ref> referenceValue
+%type <sum> sum
%union {
- vvar string
- num uint16
+ expr DcpuExpression
+ inst DcpuInstruction
+ reg DcpuRegister
+ lab DcpuLabel
+ lit DcpuLitteral
+ operand DcpuOperand
+ ref DcpuReference
+ sum DcpuSum
}
%%
+
+program: expression
+{
+ ParsedProgram.expressions = append(ParsedProgram.expressions, $1)
+}
+
+program: expression expression
+{
+ ParsedProgram.expressions = append(ParsedProgram.expressions, $1, $2)
+}
-program: expression | expression expression
expression: instruction operand ',' operand
{
- println("testing!")
- dcpuLexerReturnValue = append(dcpuLexerReturnValue, 0xF0F0)
+ expr := new(DcpuExpression)
+ expr.inst = $1
+ expr.a = $2
+ expr.b = $4
+ expr.label = ""
+ $$ = *expr
+}
+
+expression: label instruction operand ',' operand
+{
+ expr := new(DcpuExpression)
+ expr.inst = $2
+ expr.a = $3
+ expr.b = $5
+ expr.label = $1
+ $$ = *expr
+
+}
+
+operand: register
+{
+ $$ = DcpuRegister($1)
+}
+operand: reference
+{
+ $$ = $1
+}
+operand: litteral
+{
+ $$ = DcpuLitteral($1)
+}
+operand: label
+{
+ $$ = DcpuLabel($1)
}
-expression: label instruction operand ',' operand ;
+reference: '[' referenceValue ']'
+{
+ $$ = $2
+}
-operand: register | reference | litteral | label ;
-reference: '[' referenceValue ']' ;
-referenceValue: register | sum | litteral ;
+referenceValue: register
+{
+ reference := new (DcpuReference)
+ reference.ref = $1
+ $$ = *reference
+}
+referenceValue: sum
+{
+ reference := new (DcpuReference)
+ reference.ref = $1
+ $$ = *reference
+}
+referenceValue: litteral
+{
+ reference := new (DcpuReference)
+ reference.ref = $1
+ $$ = *reference
+}
sum: litteral '+' register
+{
+ sum := new(DcpuSum)
+ sum.lit = $1
+ sum.reg = $3
+ $$ = *sum
+}
View
43 dcpu/parser/dcpuLex.go
@@ -3,12 +3,19 @@ package parser
import "fmt"
import "strconv"
+var debugActivated bool = false
+func debugf(fmtstr string, args ...interface{}) {
+ if debugActivated {
+ fmt.Printf(fmtstr, args...)
+ }
+}
+
func isAlpha(r byte) bool {
return r >= 'A' && r <= 'z'
}
func isDigit(r byte) bool {
- fmt.Printf("isDigit '%c' >= '0': %t, '%c' <= '9': %t\n", r, (r >= '0'), r, (r <= '9'))
+ debugf("isDigit '%c' >= '0': %t, '%c' <= '9': %t\n", r, (r >= '0'), r, (r <= '9'))
return r >= '0' && r <= '9'
}
@@ -17,7 +24,6 @@ type DCPULex struct {
index int
currentRune byte
code string
- prog DCPUnative
initialized bool
}
@@ -29,7 +35,7 @@ func (lex *DCPULex) nextLetter() byte {
lex.currentRune = lex.code[lex.index] ;
lex.index++ ;
- fmt.Printf("lex nextLetter: '%c'\n", lex.currentRune)
+ debugf("lex nextLetter: '%c'\n", lex.currentRune)
return lex.currentRune
}
panic ("shouldnt occur in nextLetter")
@@ -44,7 +50,7 @@ func (lex *DCPULex) getRune() byte {
}
func (lex *DCPULex) findSym(yylval *yySymType) int {
- fmt.Printf("FindSym\n")
+ debugf("FindSym\n")
r := lex.getRune()
var symbol string = "";
for isAlpha(r) {
@@ -52,7 +58,7 @@ func (lex *DCPULex) findSym(yylval *yySymType) int {
r = lex.nextLetter()
}
- fmt.Printf("symbol: %s\n", symbol)
+ debugf("symbol: %s\n", symbol)
switch symbol {
case "A": fallthrough
@@ -63,8 +69,8 @@ func (lex *DCPULex) findSym(yylval *yySymType) int {
case "Z": fallthrough
case "I": fallthrough
case "J":
- yylval.vvar = symbol;
- fmt.Printf("lex: found register %s\n", symbol)
+ yylval.reg = DcpuRegister(symbol);
+ debugf("lex: found register %s\n", symbol)
return register
case "SET": fallthrough
case "ADD": fallthrough
@@ -81,8 +87,8 @@ func (lex *DCPULex) findSym(yylval *yySymType) int {
case "IFN": fallthrough
case "IFG": fallthrough
case "IFB":
- yylval.vvar = symbol;
- fmt.Printf("lex: found instruction %s\n", symbol)
+ yylval.inst = DcpuInstruction(symbol);
+ debugf("lex: found instruction %s\n", symbol)
return instruction
}
@@ -90,21 +96,22 @@ func (lex *DCPULex) findSym(yylval *yySymType) int {
}
func (lex *DCPULex) findLabel(yylval *yySymType) int {
- fmt.Printf("findLabel\n")
+ debugf("findLabel\n")
r := lex.getRune()
symbol := string(r)
for isAlpha(r) {
symbol += string(r)
r = lex.nextLetter()
}
- yylval.vvar = symbol
- fmt.Printf("lex: found label %s\n", symbol)
- return label
+ debugf("lex: found label %s\n", symbol)
+
+ yylval.lab = DcpuLabel(symbol)
+ return label
}
func (lex *DCPULex) findLitteral(yylval *yySymType) int {
- fmt.Printf("findLitteral\n")
+ debugf("findLitteral\n")
symbol := "0x"
r := lex.nextLetter()
for isDigit(r) {
@@ -113,15 +120,15 @@ func (lex *DCPULex) findLitteral(yylval *yySymType) int {
}
n, _ := strconv.ParseUint(symbol, 0, 16)
// not sure whawt to do with err
- yylval.num = uint16(n)
- fmt.Printf("lex: found litteral %x\n", yylval.num)
+ yylval.lit = DcpuLitteral(n)
+ debugf("lex: found litteral %x\n", yylval.lit)
return litteral
}
func (lex *DCPULex) Lex(yylval *yySymType) int {
r := lex.getRune()
loop:
- fmt.Printf("looping with '%c'\n", r)
+ debugf("looping with '%c'\n", r)
switch {
case r == ':':
return lex.findLabel(yylval)
@@ -137,7 +144,7 @@ loop:
goto loop
default:
- fmt.Printf("hmm should not happen?\n")
+ debugf("hmm should not happen?\n")
lex.nextLetter()
return int(r) // hmm...
}
View
104 dcpu/parser/y.go
@@ -1,19 +1,22 @@
-//line dcpuAssembly.y:2
+//line dcpuAssembly.y:3
package parser
import "fmt"
-import "dcpu"
-type DCPUnative []dcpu.Word
+var ParsedProgram DcpuProgram
-var dcpuLexerReturnValue DCPUnative = DCPUnative{}
-
-//line dcpuAssembly.y:18
+//line dcpuAssembly.y:21
type yySymType struct {
yys int
- vvar string
- num uint16
+ expr DcpuExpression
+ inst DcpuInstruction
+ reg DcpuRegister
+ lab DcpuLabel
+ lit DcpuLitteral
+ operand DcpuOperand
+ ref DcpuReference
+ sum DcpuSum
}
const instruction = 57346
@@ -331,11 +334,90 @@ yydefault:
// dummy call; replaced with literal code
switch yynt {
+ case 1:
+ //line dcpuAssembly.y:35
+ {
+ ParsedProgram.expressions = append(ParsedProgram.expressions, yyS[yypt-0].expr)
+ }
+ case 2:
+ //line dcpuAssembly.y:40
+ {
+ ParsedProgram.expressions = append(ParsedProgram.expressions, yyS[yypt-1].expr, yyS[yypt-0].expr)
+ }
case 3:
- //line dcpuAssembly.y:27
+ //line dcpuAssembly.y:45
+ {
+ expr := new(DcpuExpression)
+ expr.inst = yyS[yypt-3].inst
+ expr.a = yyS[yypt-2].operand
+ expr.b = yyS[yypt-0].operand
+ expr.label = ""
+ yyVAL.expr = *expr
+ }
+ case 4:
+ //line dcpuAssembly.y:55
+ {
+ expr := new(DcpuExpression)
+ expr.inst = yyS[yypt-3].inst
+ expr.a = yyS[yypt-2].operand
+ expr.b = yyS[yypt-0].operand
+ expr.label = yyS[yypt-4].lab
+ yyVAL.expr = *expr
+
+ }
+ case 5:
+ //line dcpuAssembly.y:66
+ {
+ yyVAL.operand = DcpuRegister(yyS[yypt-0].reg)
+ }
+ case 6:
+ //line dcpuAssembly.y:70
+ {
+ yyVAL.operand = yyS[yypt-0].ref
+ }
+ case 7:
+ //line dcpuAssembly.y:74
+ {
+ yyVAL.operand = DcpuLitteral(yyS[yypt-0].lit)
+ }
+ case 8:
+ //line dcpuAssembly.y:78
+ {
+ yyVAL.operand = DcpuLabel(yyS[yypt-0].lab)
+ }
+ case 9:
+ //line dcpuAssembly.y:83
+ {
+ yyVAL.ref = yyS[yypt-1].ref
+ }
+ case 10:
+ //line dcpuAssembly.y:88
+ {
+ reference := new (DcpuReference)
+ reference.ref = yyS[yypt-0].reg
+ yyVAL.ref = *reference
+ }
+ case 11:
+ //line dcpuAssembly.y:94
+ {
+ reference := new (DcpuReference)
+ reference.ref = yyS[yypt-0].sum
+ yyVAL.ref = *reference
+ }
+ case 12:
+ //line dcpuAssembly.y:100
+ {
+ reference := new (DcpuReference)
+ reference.ref = yyS[yypt-0].lit
+ yyVAL.ref = *reference
+ }
+ case 13:
+ //line dcpuAssembly.y:106
{
- println("testing!")
- dcpuLexerReturnValue = append(dcpuLexerReturnValue, 0xF0F0)
+ sum := new(DcpuSum)
+ sum.lit = yyS[yypt-2].lit
+ sum.reg = yyS[yypt-0].reg
+ yyVAL.sum = *sum
}
}
goto yystack /* stack new state and value */
Please sign in to comment.
Something went wrong with that request. Please try again.