diff options
| author | Bruce Hill <bitbucket@bruce-hill.com> | 2018-07-15 19:41:22 -0700 |
|---|---|---|
| committer | Bruce Hill <bitbucket@bruce-hill.com> | 2018-07-15 19:43:28 -0700 |
| commit | be06fc096aa28358914bd6a76b4ea380a04b8873 (patch) | |
| tree | 1f6c300bc8fbeb6cd84008124fca1e43f5513616 /parser.moon | |
| parent | 8a44869c4a548692a19afe5258e2540f7d351c8a (diff) | |
Major changes to how versioning and parsing work. This should be a
better path going forward to handling upgrades. Old syntax files will
stick around for compatibility purposes. Old syntax can be parsed into
valid syntax trees via the old syntax (.peg) files, and then old syntax
trees should be valid and can be upgraded via the normal code path. This
change has lots of improvements to Nomsu codegen too.
Diffstat (limited to 'parser.moon')
| -rw-r--r-- | parser.moon | 36 |
1 files changed, 19 insertions, 17 deletions
diff --git a/parser.moon b/parser.moon index 96f6b6c..39ad93a 100644 --- a/parser.moon +++ b/parser.moon @@ -73,13 +73,12 @@ setmetatable(NOMSU_DEFS, {__index:(key)=> return make_node }) -Parser = {} -NOMSU_PATTERN = do +Parser = {version:2, patterns:{}} +do -- Just for cleanliness, I put the language spec in its own file using a slightly modified -- version of the lpeg.re syntax. peg_tidier = re.compile [[ - file <- %nl* version %nl* {~ (def/comment) (%nl+ (def/comment))* %nl* ~} - version <- "--" (!"version" [^%nl])* "version" (" ")* (([0-9])+ -> set_version) ([^%nl])* + file <- %nl* {~ (def/comment) (%nl+ (def/comment))* %nl* ~} def <- anon_def / captured_def anon_def <- ({ident} (" "*) ":" {~ ((%nl " "+ def_line?)+) / def_line ~}) -> "%1 <- %2" @@ -89,24 +88,27 @@ NOMSU_PATTERN = do err <- ("(!!" { (!("!!)") .)* } "!!)") -> "(({} (%1) %%userdata) => error)" ident <- [a-zA-Z_][a-zA-Z0-9_]* comment <- "--" [^%nl]* - ]], {set_version: (v) -> Parser.version = tonumber(v), nl:NOMSU_DEFS.nl} - peg_file = io.open("nomsu.peg") - if not peg_file and package.nomsupath - for path in package.nomsupath\gmatch("[^;]+") - peg_file = io.open(path.."/nomsu.peg") - break if peg_file - assert(peg_file, "could not find nomsu.peg file") - nomsu_peg = peg_tidier\match(peg_file\read('*a')) - peg_file\close! - re.compile(nomsu_peg, NOMSU_DEFS) + ]] + for version=1,Parser.version + peg_file = io.open("nomsu.#{version}.peg") + if not peg_file and package.nomsupath + for path in package.nomsupath\gmatch("[^;]+") + peg_file = io.open(path.."/nomsu.#{version}.peg") + break if peg_file + assert(peg_file, "could not find nomsu .peg file") + nomsu_peg = peg_tidier\match(peg_file\read('*a')) + peg_file\close! + Parser.patterns[version] = re.compile(nomsu_peg, NOMSU_DEFS) -Parser.parse = (nomsu_code, source=nil)-> +Parser.parse = (nomsu_code, source=nil, version=nil)-> source or= nomsu_code.source nomsu_code = tostring(nomsu_code) + version or= nomsu_code\match("^#![^\n]*nomsu[ ]+-V[ ]*([0-9.]+)") + version = (version and tonumber(version)) or Parser.version userdata = { errors: {}, :source, comments: {} } - tree = NOMSU_PATTERN\match(nomsu_code, nil, userdata) + tree = Parser.patterns[version]\match(nomsu_code, nil, userdata) unless tree error "In file #{colored.blue tostring(source or "<unknown>")} failed to parse:\n#{colored.onyellow colored.black nomsu_code}" if type(tree) == 'number' @@ -116,7 +118,7 @@ Parser.parse = (nomsu_code, source=nil)-> keys = [k for k,v in pairs(userdata.errors)] table.sort(keys) errors = [userdata.errors[k] for k in *keys] - error("Errors occurred while parsing:\n\n"..table.concat(errors, "\n\n"), 0) + error("Errors occurred while parsing (v#{version}):\n\n"..table.concat(errors, "\n\n"), 0) tree.version = userdata.version return tree |
