microsoft/TypeAgent
Publicmirrored from https://github.com/microsoft/TypeAgentAvailable
ts/extensions/agr-language/sample.agr
224lines · modecode
| 1 | // Copyright (c) Microsoft Corporation. |
| 2 | // Licensed under the MIT License. |
| 3 | |
| 4 | // Sample Action Grammar file demonstrating syntax highlighting |
| 5 | // This file shows all the major syntax elements |
| 6 | |
| 7 | /* Block comment: |
| 8 | The grammar supports both line comments (//) and block comments. |
| 9 | */ |
| 10 | |
| 11 | // ─── Import syntax ──────────────────────────────────────────────────────────── |
| 12 | |
| 13 | // Named imports from .agr files |
| 14 | import { Cardinal, TrackName, ArtistName } from "./base.agr"; |
| 15 | |
| 16 | // Wildcard import from .agr files |
| 17 | import * from "./shared.agr"; |
| 18 | |
| 19 | // Imports from .ts schema files |
| 20 | import { GreetAction, PlayAction, PauseAction } from "./schema.ts"; |
| 21 | |
| 22 | // Source-less entity imports (no "from" clause — built-in entities) |
| 23 | import { Ordinal, CalendarDate }; |
| 24 | |
| 25 | // ─── Simple rule definition ─────────────────────────────────────────────────── |
| 26 | |
| 27 | <Start> = <Greeting> | <Command>; |
| 28 | |
| 29 | // ─── Rule with value type annotation ────────────────────────────────────────── |
| 30 | |
| 31 | <Greeting> : GreetAction = |
| 32 | hello $(name:PersonName) -> { |
| 33 | actionName: "greet", |
| 34 | parameters: { |
| 35 | name |
| 36 | } |
| 37 | } |
| 38 | | hi there -> { actionName: "greet" }; |
| 39 | |
| 40 | // ─── Union value type annotation ────────────────────────────────────────────── |
| 41 | |
| 42 | <Command> : PlayAction | PauseAction = |
| 43 | play (the)? $(track:TrackName) |
| 44 | by $(artist:ArtistName) -> { |
| 45 | actionName: "playTrack", |
| 46 | parameters: { |
| 47 | trackName: track, |
| 48 | artists: [artist] |
| 49 | } |
| 50 | } |
| 51 | | pause (the)? music? -> { actionName: "pause" }; |
| 52 | |
| 53 | // ─── Exported rule ──────────────────────────────────────────────────────────── |
| 54 | |
| 55 | export <PublicRule> = hello | goodbye; |
| 56 | |
| 57 | // ─── Spacing annotations ───────────────────────────────────────────────────── |
| 58 | |
| 59 | <Hashtag> [spacing=none] = \# $(tag:word) -> { actionName: "hashtag", parameters: { tag } }; |
| 60 | |
| 61 | <SearchPhrase> [spacing=required] = search for $(query:string) -> { |
| 62 | actionName: "search", |
| 63 | parameters: { query } |
| 64 | }; |
| 65 | |
| 66 | <CJKMixed> [spacing=auto] = $(text:string) -> text; |
| 67 | |
| 68 | <Adjacent> [spacing=optional] = $(a:word) $(b:word) -> { a, b }; |
| 69 | |
| 70 | // ─── Multiple patterns with bare results ───────────────────────────────────── |
| 71 | |
| 72 | <Volume> = |
| 73 | (turn | set) (the)? volume to $(level:number) -> { |
| 74 | actionName: "setVolume", |
| 75 | parameters: { level } |
| 76 | } |
| 77 | | volume up -> { actionName: "volumeUp" } |
| 78 | | volume down -> { actionName: "volumeDown" }; |
| 79 | |
| 80 | // Bare -> results: string literal, number, or variable reference |
| 81 | <PromptSpec> = ( |
| 82 | ('ask me' | 'confirm' | 'please confirm') -> "true" | |
| 83 | ("don't ask" | 'without asking' | 'skip') -> "false" |
| 84 | ); |
| 85 | |
| 86 | <FilterSpec> = ( |
| 87 | 'by query' $(userQuery:string) -> userQuery | |
| 88 | 'by category' $(category:string) -> category | |
| 89 | 'all' -> "all" |
| 90 | ); |
| 91 | |
| 92 | // ─── Numeric patterns ──────────────────────────────────────────────────────── |
| 93 | |
| 94 | <Cardinal> = |
| 95 | $(x:number) |
| 96 | | one -> 1 |
| 97 | | two -> 2 |
| 98 | | three -> 3 |
| 99 | | four -> 4 |
| 100 | | five -> 5; |
| 101 | |
| 102 | // ─── Entity type captures ──────────────────────────────────────────────────── |
| 103 | |
| 104 | <ScheduleEvent> = |
| 105 | schedule $(desc:string) on $(date:CalendarDate) -> { |
| 106 | actionName: "schedule", |
| 107 | parameters: { description: desc, date } |
| 108 | }; |
| 109 | |
| 110 | <PlayNth> = |
| 111 | play (the)? $(n:Ordinal) (track | song)? -> { |
| 112 | actionName: "playFromQueue", |
| 113 | parameters: { trackNumber: n } |
| 114 | }; |
| 115 | |
| 116 | // ─── Capture with rule references ───────────────────────────────────────────── |
| 117 | |
| 118 | <TrackName> = $(x:string); |
| 119 | <ArtistName> = $(x:string); |
| 120 | <PersonName> = $(x:string); |
| 121 | |
| 122 | <PlayTrack> = |
| 123 | play track $(n:<Cardinal>) -> { |
| 124 | actionName: "playTrackNumber", |
| 125 | parameters: { |
| 126 | trackNumber: n, |
| 127 | source: "current" |
| 128 | } |
| 129 | }; |
| 130 | |
| 131 | <PlayAlbum> = |
| 132 | play (the)? album $(album:<AlbumName>) -> { |
| 133 | actionName: "playAlbum", |
| 134 | parameters: { albumName: album } |
| 135 | }; |
| 136 | |
| 137 | <PlayArtist> = |
| 138 | play music by $(artist:<ArtistName>) -> { |
| 139 | actionName: "playArtist", |
| 140 | parameters: { artistName: artist } |
| 141 | }; |
| 142 | |
| 143 | <AlbumName> = $(x:string); |
| 144 | |
| 145 | // ─── Spread operator in values ──────────────────────────────────────────────── |
| 146 | |
| 147 | <MergeAction> = |
| 148 | merge $(src:string) into $(dest:string) -> { |
| 149 | actionName: "merge", |
| 150 | parameters: { ...src, destination: dest } |
| 151 | }; |
| 152 | |
| 153 | // ─── Escape sequences in string expressions ────────────────────────────────── |
| 154 | |
| 155 | <Status> = (what('s | is) | show) (playing | status)? |
| 156 | -> { actionName: "status" }; |
| 157 | |
| 158 | <EscapeDemo> = hello\ world -> "hello world"; |
| 159 | |
| 160 | // ─── Operators and grouping ────────────────────────────────────────────────── |
| 161 | |
| 162 | <Operators> = |
| 163 | one? two* three+ four // optional, zero-or-more, one-or-more |
| 164 | | (first | second | third) // alternation with grouping |
| 165 | | (item)+ // one-or-more group |
| 166 | | (prefix)* suffix; // zero-or-more group |
| 167 | |
| 168 | // ─── Optional capture quantifiers ──────────────────────────────────────────── |
| 169 | |
| 170 | <ItemList> = |
| 171 | add $(item:word)+ to $(list:string) -> { |
| 172 | actionName: "addItems", |
| 173 | parameters: { items: [item], listName: list } |
| 174 | }; |
| 175 | |
| 176 | // ─── Value expressions (enableValueExpressions mode) ───────────────────────── |
| 177 | |
| 178 | // Ternary operator |
| 179 | <Toggle> = |
| 180 | toggle $(flag:word) -> flag === "on" ? true : false; |
| 181 | |
| 182 | // Logical and nullish coalescing operators |
| 183 | <Fallback> = |
| 184 | set $(key:word) to $(val:string) -> { |
| 185 | actionName: "set", |
| 186 | parameters: { |
| 187 | key, |
| 188 | value: val ?? "default", |
| 189 | enabled: val !== "" && val !== "off" |
| 190 | } |
| 191 | }; |
| 192 | |
| 193 | // Arithmetic and comparison in values |
| 194 | <Repeat> = |
| 195 | repeat $(n:number) times -> { |
| 196 | actionName: "repeat", |
| 197 | parameters: { |
| 198 | count: n, |
| 199 | doubled: n * 2, |
| 200 | isMany: n > 5 || n === 0 |
| 201 | } |
| 202 | }; |
| 203 | |
| 204 | // Member access and optional chaining |
| 205 | <Lookup> = |
| 206 | lookup $(obj:word) -> obj.value?.name; |
| 207 | |
| 208 | // Template literals |
| 209 | <Greet> = |
| 210 | greet $(name:string) -> `Hello, ${name}!`; |
| 211 | |
| 212 | // Unary operators |
| 213 | <Negate> = |
| 214 | negate $(x:number) -> -x; |
| 215 | |
| 216 | <Check> = |
| 217 | check $(val:word) -> !val ? "empty" : typeof val; |
| 218 | |
| 219 | // Method calls and computed access |
| 220 | <Transform> = |
| 221 | transform $(data:word) -> data.items[0]?.toString(); |
| 222 | |
| 223 | /* End of sample — this block comment demonstrates |
| 224 | that multi-line block comments are highlighted. */ |
| 225 | |