1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
|
// nolint: golint
package main
import (
"io"
"strings"
"github.com/alecthomas/participle/v2/lexer"
)
// Parse a BASIC program.
func Parse(r io.Reader) (*Program, error) {
program, err := basicParser.Parse("", r)
if err != nil {
return nil, err
}
program.init()
return program, nil
}
type Program struct {
Pos lexer.Position
Commands []*Command `@@*`
Table map[int]*Command
}
type Command struct {
Pos lexer.Position
Index int
Line int `@Number`
Remark *Remark `( @@`
Input *Input ` | @@`
Let *Let ` | @@`
Goto *Goto ` | @@`
If *If ` | @@`
Print *Print ` | @@`
Call *Call ` | @@ ) EOL`
}
type Remark struct {
Pos lexer.Position
Comment string `@Comment`
}
type Call struct {
Pos lexer.Position
Name string `@Ident`
Args []*Expression `"(" ( @@ ( "," @@ )* )? ")"`
}
type Print struct {
Pos lexer.Position
Expression *Expression `"PRINT" @@`
}
type Input struct {
Pos lexer.Position
Variable string `"INPUT" @Ident`
}
type Let struct {
Pos lexer.Position
Variable string `"LET" @Ident`
Value *Expression `"=" @@`
}
type Goto struct {
Pos lexer.Position
Line int `"GOTO" @Number`
}
type If struct {
Pos lexer.Position
Condition *Expression `"IF" @@`
Line int `"THEN" @Number`
}
type Operator string
func (o *Operator) Capture(s []string) error {
*o = Operator(strings.Join(s, ""))
return nil
}
type Value struct {
Pos lexer.Position
Number *float64 ` @Number`
Variable *string `| @Ident`
String *string `| @String`
Call *Call `| @@`
Subexpression *Expression `| "(" @@ ")"`
}
type Factor struct {
Pos lexer.Position
Base *Value `@@`
Exponent *Value `( "^" @@ )?`
}
type OpFactor struct {
Pos lexer.Position
Operator Operator `@("*" | "/")`
Factor *Factor `@@`
}
type Term struct {
Pos lexer.Position
Left *Factor `@@`
Right []*OpFactor `@@*`
}
type OpTerm struct {
Pos lexer.Position
Operator Operator `@("+" | "-")`
Term *Term `@@`
}
type Cmp struct {
Pos lexer.Position
Left *Term `@@`
Right []*OpTerm `@@*`
}
type OpCmp struct {
Pos lexer.Position
Operator Operator `@("=" | "<" "=" | ">" "=" | "<" | ">" | "!" "=")`
Cmp *Cmp `@@`
}
type Expression struct {
Pos lexer.Position
Left *Cmp `@@`
Right []*OpCmp `@@*`
}
|