From 904f651897c90a864d35cfc724ad3787c7d87357 Mon Sep 17 00:00:00 2001 From: Glen Whitney Date: Thu, 11 Feb 2021 10:02:43 -0800 Subject: [PATCH] feat: Add syntax for string literals Also rudimentary code generation. The difficulty is that for Haskell generation, we need to know whether an expression is a string or in to send it to standard output. So we will need to begin implementation of a type system for fostr. --- syntax/fostr.sdf3 | 21 +++++++++++++++------ tests/hw.fos | 1 + trans/haskell.str | 12 ++++++++++++ trans/javascript.str | 10 ++++++++++ trans/python.str | 1 + 5 files changed, 39 insertions(+), 6 deletions(-) create mode 100644 tests/hw.fos diff --git a/syntax/fostr.sdf3 b/syntax/fostr.sdf3 index 4a39131..7805b3f 100644 --- a/syntax/fostr.sdf3 +++ b/syntax/fostr.sdf3 @@ -8,6 +8,14 @@ context-free start-symbols Start +lexical sorts + + STRING_LITERAL + +lexical syntax + + STRING_LITERAL = ~[\']* + context-free sorts Start LineSeq Line OptTermEx TermExLst TermEx Ex @@ -29,13 +37,14 @@ context-free syntax TermEx.Terminate = <;> - Ex.Int = INT - Ex.Stream = - Ex.Sum = [[Ex] + [Ex]] {left} - Ex.Gets = [[Ex] << [Ex]] {left} - Ex.To = [[Ex] >> [Ex]] {left} + Ex.Int = INT + Ex.LitString = <''> + Ex.Stream = + Ex.Sum = < + > {left} + Ex.Gets = [[Ex] << [Ex]] {left} + Ex.To = [[Ex] >> [Ex]] {left} - Ex = <()> {bracket} + Ex = <()> {bracket} context-free priorities diff --git a/tests/hw.fos b/tests/hw.fos new file mode 100644 index 0000000..90fc0d4 --- /dev/null +++ b/tests/hw.fos @@ -0,0 +1 @@ +stream << 'Hello, world!' diff --git a/trans/haskell.str b/trans/haskell.str index eae335e..63c969e 100644 --- a/trans/haskell.str +++ b/trans/haskell.str @@ -22,6 +22,8 @@ rules hs: Stream() -> ("StdIO", "") hs: Int(x) -> (x, "") + hs: LitString(x) + -> ($["[x]"], "") hs: Sum( (c, p), (d, q)) -> ($[([c] + [d])], (p,q)) hs: Gets((c, p), (d, q)) -> (c,d,(p,q),"fosgt") @@ -35,7 +37,17 @@ rules hs: Terminate((c,p)) -> ($[[c];;], p) hs: Sequence(l) -> (l, l) + /* Characters we need to escape in Haskell string constants */ + Hascape: ['\t' | cs ] -> ['\', 't' | cs ] + /* I think I can just use ASCII constants for characters... */ + Hascape: [ 0 | cs ] -> ['\', '0' | cs ] + Hascape: [ 7 | cs ] -> ['\', 'a' | cs ] // Alert + Hascape: [ 8 | cs ] -> ['\', 'b' | cs ] // Backspace + Hascape: [ 11 | cs ] -> ['\', 'v' | cs ] // Vertical tab + Hascape: [ 12 | cs ] -> ['\', 'f' | cs ] // Form feed + strategies + HaskellEscape = Escape <+ Hascape haskell = bottomup(try(hs)) diff --git a/trans/javascript.str b/trans/javascript.str index 605b46a..d0d97fe 100644 --- a/trans/javascript.str +++ b/trans/javascript.str @@ -13,13 +13,23 @@ rules js: Stream() -> $[Stdio] js: Int(x) -> x + js: LitString(x) -> $['[x]'] js: Sum(x,y) -> $[[x] + [y]] js: Gets(x, y) -> $[[x].gets([y])] js: To(x, y) -> $[to([x],[y])] js: Terminate(x) -> x js: Sequence(l) -> l + /* Characters we need to escape in Javascript string constants */ + Jscape: ['\t' | cs ] -> ['\', 't' | cs ] + /* I think I can just use ASCII constants for characters... */ + Jscape: [ 0 | cs ] -> ['\', '0' | cs ] + Jscape: [ 8 | cs ] -> ['\', 'b' | cs ] // Backspace + Jscape: [ 11 | cs ] -> ['\', 'v' | cs ] // Vertical tab + Jscape: [ 12 | cs ] -> ['\', 'f' | cs ] // Form feed + strategies + JavaEscape = Escape <+ Jscape javascript = bottomup(try(js)) diff --git a/trans/python.str b/trans/python.str index 238c006..d745cee 100644 --- a/trans/python.str +++ b/trans/python.str @@ -15,6 +15,7 @@ rules py: Stream() -> $[Stdio] py: Int(x) -> x + py: LitString(x) -> $[r'[x]'] py: Sum(x,y) -> $[[x] + [y]] py: Gets(x, y) -> $[[x].gets([y])] py: To(x, y) -> $[to([x],[y])]