-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
> added a new function "NewLexerFromYamlConfig" that can generate a lexer based on yaml config source. > added corresponding tests and examples demonstrating the config fields. > added an example "minilisp" inside the examples folder demonstrating using the NewLexerFromYamlConfig function.
- Loading branch information
Showing
8 changed files
with
268 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# this file should exist in the same directory as the binary | ||
lexer: | ||
rules : | ||
- type : "<lparen>" | ||
regex : "\\(" | ||
- type : "<rparen>" | ||
regex : "\\)" | ||
- type : "<op_plus>" | ||
regex : "\\+" | ||
- type : "<op_minus>" | ||
regex : "-" | ||
- type : "<integer>" | ||
regex : "[0-9]+" | ||
ignore : | ||
- "\\s+" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"io/ioutil" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
|
||
"github.com/nayas360/goply" | ||
) | ||
|
||
var source = `(+ 10 (- 15 5))` | ||
|
||
func main() { | ||
yamlConfig, err := getYamlConfig() | ||
if err != nil { | ||
panic(err) | ||
} | ||
// get the lexer from the config and source | ||
lex, err := goply.NewLexerFromYamlConfig(yamlConfig, source) | ||
if err != nil { | ||
panic(err) | ||
} | ||
// get the tokens | ||
tokens, err := lex.GetTokens() | ||
if err != nil { | ||
panic(err) | ||
} | ||
// print the tokens | ||
for _, token := range tokens { | ||
fmt.Printf("Got %s : %s\n", token.Type, token.Value) | ||
} | ||
} | ||
|
||
func getYamlConfig() ([]byte, error) { | ||
var GOP string | ||
|
||
for _, p := range os.Environ() { | ||
ps := strings.Split(p, "=") | ||
if ps[0] == "GOPATH" { | ||
GOP = strings.Split(ps[1], ":")[0] | ||
} | ||
} | ||
|
||
// load lexer definition from file | ||
ycp, err := filepath.Abs(GOP + "/src/github.com/nayas360/goply/examples/minilisp/lex.yml") | ||
if err != nil { | ||
panic(err) | ||
} | ||
// read the config | ||
yamlConfig, err := ioutil.ReadFile(ycp) | ||
return yamlConfig, err | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package goply | ||
|
||
import ( | ||
"fmt" | ||
"regexp" | ||
|
||
"gopkg.in/yaml.v2" | ||
) | ||
|
||
// Struct used to read the yaml config into | ||
type goplyYamlConfig struct { | ||
Lexer struct { | ||
StrictMode bool `yaml:"strict_mode,omitempty"` | ||
Rules []struct { | ||
Type string `yaml:"type"` | ||
Regex string `yaml:"regex"` | ||
} `yaml:"rules"` | ||
Ignore []string `yaml:"ignore"` | ||
} `yaml:"lexer"` | ||
} | ||
|
||
// Create a lexer from a yaml config | ||
// the config should be the config source and not a file path | ||
// this allows loading the config from file as well as memory | ||
// like the source file | ||
// returns an error if could not read the yaml properly | ||
func NewLexerFromYamlConfig(yamlConfig []byte, source string) (*Lexer, error) { | ||
var gyc goplyYamlConfig | ||
// strict mode set to true by default | ||
gyc.Lexer.StrictMode = true | ||
err := yaml.UnmarshalStrict([]byte(yamlConfig), &gyc) | ||
if err != nil { | ||
return nil, err | ||
} | ||
lex := &Lexer{ls: LexerState{SourceLength: len(source) - 1, Source: source}, | ||
lexRules: make(map[string]*regexp.Regexp), lexerErrorFunc: defaultLexerError, strictMode: gyc.Lexer.StrictMode} | ||
|
||
for _, rule := range gyc.Lexer.Rules { | ||
if rule.Type != "" && rule.Regex != "" { | ||
lex.AddRule(rule.Type, rule.Regex) | ||
} else { | ||
return nil, fmt.Errorf("malformed config file, \"type\" or \"regex\" fields missing from a rule") | ||
} | ||
} | ||
for _, rule := range gyc.Lexer.Ignore { | ||
if rule != "" { | ||
lex.Ignore(rule) | ||
} else { | ||
return nil, fmt.Errorf("malformed config file, empty rule in \"ignore\"") | ||
} | ||
} | ||
return lex, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
package goply_test | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/nayas360/goply" | ||
) | ||
|
||
func TestNewLexerFromYamlConfig(t *testing.T) { | ||
yamlSource := ` | ||
lexer: | ||
rules : | ||
- type : "<var_kw>" | ||
regex : "var" | ||
- type : "<eq>" | ||
regex : "=" | ||
- type : "<integer>" | ||
regex : "[0-9]+" | ||
ignore : | ||
- "\\s+" | ||
` | ||
source := "var = 123" | ||
lex, err := goply.NewLexerFromYamlConfig([]byte(yamlSource), source) | ||
if err != nil { | ||
t.Errorf("could not create a new lexer from yaml config, %s", err) | ||
} | ||
tokens, err := lex.GetTokens() | ||
if err != nil { | ||
t.Errorf("got error instead of tokens, %s", err) | ||
} | ||
fmt.Println(tokens) | ||
if len(tokens) != 3 { | ||
t.Errorf("expected 3 tokens got, %s", len(tokens)) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters