diff --git a/src/dreamchecker/tests/new_tests.rs b/src/dreamchecker/tests/new_tests.rs index 245eec9a..2f434912 100644 --- a/src/dreamchecker/tests/new_tests.rs +++ b/src/dreamchecker/tests/new_tests.rs @@ -4,7 +4,7 @@ extern crate dreamchecker as dc; use dc::test_helpers::*; pub const NEW_DOT_ERRORS: &[(u32, u16, &str)] = &[ - (13, 14, "got '(', expected one of: operator, field access, ';'"), + (12, 14, "got '(', expected one of: operator, field access, ';'"), ]; #[test] @@ -20,7 +20,6 @@ fn new_dot() { new /obj() new /obj{name = "foo"}() new .subtype() - new L[1]() new src.name new foo()() new /obj[0]() // TODO: see parser.rs @@ -28,3 +27,18 @@ fn new_dot() { "##.trim(); check_errors_match(code, NEW_DOT_ERRORS); } + +pub const NEW_PRECEDENCE_ERRORS: &[(u32, u16, &str)] = &[ + (4, 13, "got '(', expected one of: operator, field access, ';'"), +]; + +#[test] +fn new_precedence() { + let code = r##" +/mob/subtype +/mob/proc/foo() +/mob/proc/test() + new L[1]() +"##.trim(); + check_errors_match(code, NEW_PRECEDENCE_ERRORS); +} diff --git a/src/dreammaker/ast.rs b/src/dreammaker/ast.rs index 6c6f44e3..7cf059f2 100644 --- a/src/dreammaker/ast.rs +++ b/src/dreammaker/ast.rs @@ -329,7 +329,7 @@ pub enum NewType { /// A "mini-expression" in which to find the prefab to instantiate. MiniExpr { ident: Ident, - fields: Vec, + fields: Vec, }, } @@ -680,21 +680,16 @@ pub enum Follow { Call(IndexKind, Ident, Vec), } -/// Like a `Follow` but supports index or fields only. +/// Like a `Follow` but only supports field accesses. #[derive(Debug, Clone, PartialEq)] -pub enum IndexOrField { - /// Index the value by an expression. - Index(Box), - /// Access a field of the value. - Field(IndexKind, Ident), +pub struct Field { + pub kind: IndexKind, + pub ident: Ident, } -impl From for Follow { - fn from(input: IndexOrField) -> Follow { - match input { - IndexOrField::Index(expr) => Follow::Index(expr), - IndexOrField::Field(kind, name) => Follow::Field(kind, name), - } +impl From for Follow { + fn from(field: Field) -> Follow { + Follow::Field(field.kind, field.ident) } } diff --git a/src/dreammaker/parser.rs b/src/dreammaker/parser.rs index 7ddba97e..c24bd43b 100644 --- a/src/dreammaker/parser.rs +++ b/src/dreammaker/parser.rs @@ -1890,7 +1890,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { let start = self.updated_location(); let term = match self.next("term")? { - // term :: 'new' (prefab | (ident (index | field)*))? arglist? + // term :: 'new' (prefab | (ident field*))? arglist? Token::Ident(ref i, _) if i == "new" => { // It's not entirely clear what is supposed to be valid here. // Some things definitely are: @@ -1898,7 +1898,6 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { // * new /obj() // * new /obj{name = "foo"}() // * new .relative/path() - // * new some_list[0]() // * new various.field.accesses() // But some things definitely aren't: // * new some_proc()() - first parens belong to the 'new' @@ -1921,7 +1920,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } else if let Some(ident) = self.ident()? { let mut fields = Vec::new(); let mut belongs_to = vec![ident.clone()]; - while let Some(item) = self.index_or_field(&mut belongs_to, false)? { + while let Some(item) = self.field(&mut belongs_to, false)? { fields.push(item); } NewType::MiniExpr { ident, fields } @@ -2163,17 +2162,9 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { } // TODO: somehow fix the fact that this is basically copy-pasted from - // follow() above, except for the very end. - fn index_or_field(&mut self, belongs_to: &mut Vec, in_ternary: bool) -> Status { + // follow() above. + fn field(&mut self, belongs_to: &mut Vec, in_ternary: bool) -> Status { let kind = match self.next("field access")? { - // follow :: '[' expression ']' - Token::Punct(Punctuation::LBracket) => { - belongs_to.clear(); - let expr = require!(self.expression()); - require!(self.exact(Token::Punct(Punctuation::RBracket))); - return success(IndexOrField::Index(Box::new(expr))) - } - // follow :: '.' ident // TODO: only apply these rules if there is no whitespace around the punctuation Token::Punct(Punctuation::Dot) => IndexKind::Dot, @@ -2204,7 +2195,7 @@ impl<'ctx, 'an, 'inp> Parser<'ctx, 'an, 'inp> { self.annotate_precise(start..end, || Annotation::ScopedVar(belongs_to.clone(), ident.clone())); belongs_to.push(ident.clone()); } - success(IndexOrField::Field(kind, ident)) + success(Field { kind, ident }) } /// a parenthesized, comma-separated list of expressions